mirror of https://github.com/dswd/vpncloud.git
Include libsodium in builds
This commit is contained in:
parent
03793052a3
commit
ec6d1b544f
14
.travis.yml
14
.travis.yml
|
@ -11,9 +11,10 @@ before_script:
|
||||||
- ! ' set -e ;
|
- ! ' set -e ;
|
||||||
pip install ''travis-cargo<0.2'' --user ;
|
pip install ''travis-cargo<0.2'' --user ;
|
||||||
export PATH=$HOME/.local/bin:$PATH ;
|
export PATH=$HOME/.local/bin:$PATH ;
|
||||||
wget https://github.com/jedisct1/libsodium/releases/download/1.0.3/libsodium-1.0.3.tar.gz ;
|
export VERSION=1.0.6 ;
|
||||||
tar xvfz libsodium-1.0.3.tar.gz ;
|
wget https://github.com/jedisct1/libsodium/releases/download/$VERSION/libsodium-$VERSION.tar.gz ;
|
||||||
pushd libsodium-1.0.3 ;
|
tar xvfz libsodium-$VERSION.tar.gz ;
|
||||||
|
pushd libsodium-$VERSION ;
|
||||||
./configure --prefix=/usr ;
|
./configure --prefix=/usr ;
|
||||||
make ;
|
make ;
|
||||||
sudo make install ;
|
sudo make install ;
|
||||||
|
@ -22,9 +23,8 @@ before_script:
|
||||||
script:
|
script:
|
||||||
- ! ' set -e ;
|
- ! ' set -e ;
|
||||||
travis-cargo build ;
|
travis-cargo build ;
|
||||||
travis-cargo build -- --features "crypto" ;
|
travis-cargo test ;
|
||||||
travis-cargo test -- --features "crypto" ;
|
travis-cargo bench ;
|
||||||
travis-cargo bench -- --features "crypto" ;
|
|
||||||
travis-cargo coverage ;
|
travis-cargo coverage ;
|
||||||
'
|
'
|
||||||
addons:
|
addons:
|
||||||
|
@ -37,7 +37,7 @@ after_success:
|
||||||
- ! ' set -e ;
|
- ! ' set -e ;
|
||||||
rm -rf target/kcov ;
|
rm -rf target/kcov ;
|
||||||
rm target/debug/vpncloud-* ;
|
rm target/debug/vpncloud-* ;
|
||||||
cargo test --features "crypto" ;
|
cargo test ;
|
||||||
kcov/build/src/kcov --exclude-pattern=/libsodium/,/x86_64-linux-gnu/,/.cargo --coveralls-id=$TRAVIS_JOB_ID target/kcov target/debug/vpncloud-* ;
|
kcov/build/src/kcov --exclude-pattern=/libsodium/,/x86_64-linux-gnu/,/.cargo --coveralls-id=$TRAVIS_JOB_ID target/kcov target/debug/vpncloud-* ;
|
||||||
'
|
'
|
||||||
notifications:
|
notifications:
|
||||||
|
|
|
@ -6,9 +6,9 @@ dependencies = [
|
||||||
"epoll 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"epoll 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gcc 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libsodium-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"signal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"signal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -93,15 +93,6 @@ name = "libc"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libsodium-sys"
|
|
||||||
version = "0.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
|
@ -10,7 +10,6 @@ repository = "https://github.com/dswd/vpncloud.rs"
|
||||||
keywords = ["vpn", "p2p", "tun", "tap", "network"]
|
keywords = ["vpn", "p2p", "tun", "tap", "network"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
docopt = "0.6"
|
docopt = "0.6"
|
||||||
|
@ -20,12 +19,11 @@ epoll = "0.2"
|
||||||
signal = "0.1"
|
signal = "0.1"
|
||||||
nix = "0.4"
|
nix = "0.4"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libsodium-sys = {version = "0.0.9", optional = true}
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
gcc = "0.3"
|
||||||
|
pkg-config = "0.3.6"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
crypto = ["libsodium-sys"] #not default as it requires external library
|
|
||||||
bench = []
|
bench = []
|
||||||
|
|
2
build.rs
2
build.rs
|
@ -1,5 +1,7 @@
|
||||||
extern crate gcc;
|
extern crate gcc;
|
||||||
|
extern crate pkg_config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
pkg_config::find_library("libsodium").unwrap();
|
||||||
gcc::Config::new().file("src/c/tuntap.c").include("src").compile("libtuntap.a");
|
gcc::Config::new().file("src/c/tuntap.c").include("src").compile("libtuntap.a");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,11 @@ DEPENDENCIES=debhelper devscripts
|
||||||
default: clean build
|
default: clean build
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(PACKAGE)_*.deb $(PACKAGE)-nocrypto_*.deb
|
build: $(PACKAGE)_*.deb
|
||||||
$(PACKAGE)_*.deb:
|
$(PACKAGE)_*.deb:
|
||||||
(cd $(PACKAGE); make clean; debuild -b -us -uc; cd ..)
|
(cd $(PACKAGE); make clean; debuild -b -us -uc; cd ..)
|
||||||
$(PACKAGE)-nocrypto_*.deb:
|
|
||||||
(cd $(PACKAGE)-nocrypto; make clean; debuild -b -us -uc; cd ..)
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
(cd $(PACKAGE); debuild clean; cd ..)
|
(cd $(PACKAGE); debuild clean; cd ..)
|
||||||
(cd $(PACKAGE)-nocrypto; debuild clean; cd ..)
|
rm -rf $(PACKAGE)_*
|
||||||
rm -rf $(PACKAGE)_* $(PACKAGE)-nocrypto_*
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
build: vpncloud.1 vpncloud
|
|
||||||
|
|
||||||
vpncloud.1: vpncloud.1.ronn
|
|
||||||
ronn -r vpncloud.1.ronn
|
|
||||||
|
|
||||||
vpncloud.1.ronn: ../../vpncloud.md
|
|
||||||
cp ../../vpncloud.md vpncloud.1.ronn
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f vpncloud.1* vpncloud ../../target/release/vpncloud
|
|
||||||
|
|
||||||
vpncloud: ../../target/release/vpncloud
|
|
||||||
cp ../../target/release/vpncloud vpncloud
|
|
||||||
|
|
||||||
../../target/release/vpncloud: ../../src/*.rs ../../Cargo.toml ../../src/usage.txt ../../src/c/*
|
|
||||||
(cd ../..; cargo build --release)
|
|
||||||
|
|
||||||
install:
|
|
||||||
install -d $(DESTDIR)/usr/bin
|
|
||||||
install -m 755 vpncloud $(DESTDIR)/usr/bin/vpncloud
|
|
|
@ -1,11 +0,0 @@
|
||||||
vpncloud-nocrypto (0.2.0) stable; urgency=medium
|
|
||||||
|
|
||||||
* More stable release
|
|
||||||
|
|
||||||
-- Dennis Schwerdel <schwerdel@informatik.uni-kl.de> Thu, 26 Nov 2015 17:41:40 +0100
|
|
||||||
|
|
||||||
vpncloud-nocrypto (0.1.0) stable; urgency=medium
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
|
|
||||||
-- Dennis Schwerdel <schwerdel@informatik.uni-kl.de> Tue, 24 Nov 2015 09:31:47 +0100
|
|
|
@ -1 +0,0 @@
|
||||||
7
|
|
|
@ -1,12 +0,0 @@
|
||||||
Source: vpncloud-nocrypto
|
|
||||||
Section: misc
|
|
||||||
Priority: extra
|
|
||||||
Maintainer: Dennis Schwerdel <schwerdel@informatik.uni-kl.de>
|
|
||||||
Build-Depends: debhelper (>= 7), ruby-ronn, rust-stable
|
|
||||||
Standards-Version: 3.8.3
|
|
||||||
|
|
||||||
Package: vpncloud-nocrypto
|
|
||||||
Architecture: amd64
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
|
||||||
Conflicts: vpncloud
|
|
||||||
Description: Peer-to-peer VPN (built without crypto support)
|
|
|
@ -1,31 +0,0 @@
|
||||||
Upstream Author:
|
|
||||||
|
|
||||||
Dennis Schwerdel <schwerdel@informatik.uni-kl.de>
|
|
||||||
|
|
||||||
Copyright:
|
|
||||||
|
|
||||||
Copyright (C) 2015 Dennis Schwerdel, University of Kaiserslautern
|
|
||||||
|
|
||||||
License:
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This package is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
On Debian systems, the complete text of the GNU General
|
|
||||||
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
|
||||||
|
|
||||||
The Debian packaging is:
|
|
||||||
|
|
||||||
Copyright (C) 2015 Dennis Schwerdel, University of Kaiserslautern
|
|
||||||
|
|
||||||
and is licensed under the GPL version 3, see above.
|
|
|
@ -1 +0,0 @@
|
||||||
misc:Depends=
|
|
|
@ -1 +0,0 @@
|
||||||
vpncloud.1
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
%:
|
|
||||||
dh $@
|
|
|
@ -13,7 +13,7 @@ vpncloud: ../../target/release/vpncloud
|
||||||
cp ../../target/release/vpncloud vpncloud
|
cp ../../target/release/vpncloud vpncloud
|
||||||
|
|
||||||
../../target/release/vpncloud: ../../src/*.rs ../../Cargo.toml ../../src/usage.txt ../../src/c/*
|
../../target/release/vpncloud: ../../src/*.rs ../../Cargo.toml ../../src/usage.txt ../../src/c/*
|
||||||
(cd ../..; cargo build --release --features "crypto")
|
(cd ../..; cargo build --release)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -d $(DESTDIR)/usr/bin
|
install -d $(DESTDIR)/usr/bin
|
||||||
|
|
|
@ -2,11 +2,10 @@ Source: vpncloud
|
||||||
Section: misc
|
Section: misc
|
||||||
Priority: extra
|
Priority: extra
|
||||||
Maintainer: Dennis Schwerdel <schwerdel@informatik.uni-kl.de>
|
Maintainer: Dennis Schwerdel <schwerdel@informatik.uni-kl.de>
|
||||||
Build-Depends: debhelper (>= 7), ruby-ronn, rust-stable, libsodium-dev
|
Build-Depends: debhelper (>= 7), ruby-ronn, rust-stable
|
||||||
Standards-Version: 3.8.3
|
Standards-Version: 3.8.3
|
||||||
|
|
||||||
Package: vpncloud
|
Package: vpncloud
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libsodium13
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
Conflicts: vpncloud-nocrypto
|
|
||||||
Description: Peer-to-peer VPN
|
Description: Peer-to-peer VPN
|
||||||
|
|
|
@ -53,10 +53,11 @@ The test is run in 3 steps:
|
||||||
|
|
||||||
|
|
||||||
| Throughput test | Bandwidth | CPU usage (one core) |
|
| Throughput test | Bandwidth | CPU usage (one core) |
|
||||||
| -------------------- | ------------- | -------------------- |
|
| ----------------------------- | ------------- | -------------------- |
|
||||||
| Without VpnCloud | 926 Mbits/sec | - |
|
| Without VpnCloud | 926 Mbits/sec | - |
|
||||||
| Unencrypted VpnCloud | 873 Mbits/sec | 80% / 95% |
|
| Unencrypted VpnCloud | 873 Mbits/sec | 80% / 95% |
|
||||||
| Encrypted VpnCloud | 770 Mbits/sec | 100% |
|
| Encrypted VpnCloud (ChaCha20) | 770 Mbits/sec | 100% |
|
||||||
|
| Encrypted VpnCloud (AES256) | 813 Mbits/sec | 90% / 100% |
|
||||||
|
|
||||||
|
|
||||||
### Latency
|
### Latency
|
||||||
|
@ -71,12 +72,14 @@ assumed to be half of the RTT.
|
||||||
|
|
||||||
|
|
||||||
| Payload size | 100 bytes | 500 bytes | 1000 bytes |
|
| Payload size | 100 bytes | 500 bytes | 1000 bytes |
|
||||||
| -------------------- | --------- | --------- | ---------- |
|
| ----------------------------- | --------- | --------- | ---------- |
|
||||||
| Without VpnCloud | 158 µs | 165 µs | 178 µs |
|
| Without VpnCloud | 158 µs | 165 µs | 178 µs |
|
||||||
| Unencrypted VpnCloud | 210 µs | 216 µs | 237 µs |
|
| Unencrypted VpnCloud | 210 µs | 216 µs | 237 µs |
|
||||||
| Difference | +52 µs | +51 µs | +59 µs |
|
| Difference | +52 µs | +51 µs | +59 µs |
|
||||||
| Encrypted VpnCloud | 218 µs | 230 µs | 257 µs |
|
| Encrypted VpnCloud (ChaCha20) | 218 µs | 230 µs | 257 µs |
|
||||||
| Difference | +8 µs | +14 µs | +20 µs |
|
| Difference | +8 µs | +14 µs | +20 µs |
|
||||||
|
| Encrypted VpnCloud (AES256) | 224 µs | 230 µs | 255 µs |
|
||||||
|
| Difference | +14 µs | +14 µs | +18 µs |
|
||||||
|
|
||||||
|
|
||||||
### Conclusion
|
### Conclusion
|
||||||
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
use std::{mem, ptr};
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use libc::{size_t, c_char, c_ulonglong, c_int};
|
||||||
|
|
||||||
|
use super::types::Error;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_chacha20poly1305_KEYBYTES: usize = 32;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_chacha20poly1305_NSECBYTES: usize = 0;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_chacha20poly1305_NPUBBYTES: usize = 8;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_chacha20poly1305_ABYTES: usize = 16;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_aes256gcm_KEYBYTES: usize = 32;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_aes256gcm_NSECBYTES: usize = 0;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_aes256gcm_NPUBBYTES: usize = 12;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_aead_aes256gcm_ABYTES: usize = 16;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_pwhash_scryptsalsa208sha256_SALTBYTES: usize = 32;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_pwhash_scryptsalsa208sha256_STRBYTES: usize = 102;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: usize = 524288;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16777216;
|
||||||
|
|
||||||
|
#[link(name="sodium", kind="static")]
|
||||||
|
extern {
|
||||||
|
pub fn sodium_init() -> c_int;
|
||||||
|
pub fn randombytes_buf(buf: *mut u8, size: size_t);
|
||||||
|
pub fn sodium_version_string() -> *const c_char;
|
||||||
|
pub fn crypto_pwhash_scryptsalsa208sha256(
|
||||||
|
out: *mut u8,
|
||||||
|
outlen: c_ulonglong,
|
||||||
|
passwd: *const u8,
|
||||||
|
passwdlen: c_ulonglong,
|
||||||
|
salt: *const [u8; crypto_pwhash_scryptsalsa208sha256_SALTBYTES],
|
||||||
|
opslimit: c_ulonglong,
|
||||||
|
memlimit: size_t) -> c_int;
|
||||||
|
pub fn crypto_aead_chacha20poly1305_encrypt(
|
||||||
|
c: *mut u8,
|
||||||
|
clen: *mut c_ulonglong,
|
||||||
|
m: *const u8,
|
||||||
|
mlen: c_ulonglong,
|
||||||
|
ad: *const u8,
|
||||||
|
adlen: c_ulonglong,
|
||||||
|
nsec: *const [u8; crypto_aead_chacha20poly1305_NSECBYTES],
|
||||||
|
npub: *const [u8; crypto_aead_chacha20poly1305_NPUBBYTES],
|
||||||
|
k: *const [u8; crypto_aead_chacha20poly1305_KEYBYTES]) -> c_int;
|
||||||
|
pub fn crypto_aead_chacha20poly1305_decrypt(
|
||||||
|
m: *mut u8,
|
||||||
|
mlen: *mut c_ulonglong,
|
||||||
|
nsec: *mut [u8; crypto_aead_chacha20poly1305_NSECBYTES],
|
||||||
|
c: *const u8,
|
||||||
|
clen: c_ulonglong,
|
||||||
|
ad: *const u8,
|
||||||
|
adlen: c_ulonglong,
|
||||||
|
npub: *const [u8; crypto_aead_chacha20poly1305_NPUBBYTES],
|
||||||
|
k: *const [u8; crypto_aead_chacha20poly1305_KEYBYTES]) -> c_int;
|
||||||
|
pub fn crypto_aead_aes256gcm_encrypt(
|
||||||
|
c: *mut u8,
|
||||||
|
clen: *mut c_ulonglong,
|
||||||
|
m: *const u8,
|
||||||
|
mlen: c_ulonglong,
|
||||||
|
ad: *const u8,
|
||||||
|
adlen: c_ulonglong,
|
||||||
|
nsec: *const [u8; crypto_aead_aes256gcm_NSECBYTES],
|
||||||
|
npub: *const [u8; crypto_aead_aes256gcm_NPUBBYTES],
|
||||||
|
k: *const [u8; crypto_aead_aes256gcm_KEYBYTES]) -> c_int;
|
||||||
|
pub fn crypto_aead_aes256gcm_decrypt(
|
||||||
|
m: *mut u8,
|
||||||
|
mlen: *mut c_ulonglong,
|
||||||
|
nsec: *mut [u8; crypto_aead_aes256gcm_NSECBYTES],
|
||||||
|
c: *const u8,
|
||||||
|
clen: c_ulonglong,
|
||||||
|
ad: *const u8,
|
||||||
|
adlen: c_ulonglong,
|
||||||
|
npub: *const [u8; crypto_aead_aes256gcm_NPUBBYTES],
|
||||||
|
k: *const [u8; crypto_aead_aes256gcm_KEYBYTES]) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(RustcDecodable, Debug)]
|
||||||
|
pub enum CryptoMethod {
|
||||||
|
ChaCha20, AES256
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Crypto {
|
||||||
|
None,
|
||||||
|
ChaCha20Poly1305{key: [u8; 32], nonce: [u8; 8]},
|
||||||
|
AES256GCM{key: [u8; 32], nonce: [u8; 12]}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_nonce_8(nonce: &mut [u8; 8]) {
|
||||||
|
unsafe {
|
||||||
|
let num = mem::transmute::<&mut [u8; 8], &mut u64>(nonce);
|
||||||
|
*num = num.wrapping_add(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_nonce_12(nonce: &mut [u8; 12]) {
|
||||||
|
for i in 0..12 {
|
||||||
|
let mut num = nonce[11-i];
|
||||||
|
num = num.wrapping_add(1);
|
||||||
|
nonce[11-i] = num;
|
||||||
|
if num > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Crypto {
|
||||||
|
pub fn init() {
|
||||||
|
unsafe { sodium_init() };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sodium_version() -> String {
|
||||||
|
unsafe {
|
||||||
|
CStr::from_ptr(sodium_version_string()).to_string_lossy().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
&Crypto::None => 0,
|
||||||
|
&Crypto::ChaCha20Poly1305{key: _, nonce: _} => 1,
|
||||||
|
&Crypto::AES256GCM{key: _, nonce: _} => 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nonce_bytes(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
&Crypto::None => 0,
|
||||||
|
&Crypto::ChaCha20Poly1305{key: _, ref nonce} => nonce.len(),
|
||||||
|
&Crypto::AES256GCM{key: _, ref nonce} => nonce.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn additional_bytes(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
&Crypto::None => 0,
|
||||||
|
&Crypto::ChaCha20Poly1305{key: _, nonce: _} => crypto_aead_chacha20poly1305_ABYTES,
|
||||||
|
&Crypto::AES256GCM{key: _, nonce: _} => crypto_aead_aes256gcm_ABYTES
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_shared_key(method: CryptoMethod, password: &str) -> Self {
|
||||||
|
let salt = "vpncloudVPNCLOUDvpncl0udVpnCloud".as_bytes();
|
||||||
|
assert_eq!(salt.len(), crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
||||||
|
let mut key = [0; crypto_pwhash_scryptsalsa208sha256_STRBYTES];
|
||||||
|
let res = unsafe { crypto_pwhash_scryptsalsa208sha256(
|
||||||
|
key.as_mut_ptr(),
|
||||||
|
key.len() as u64,
|
||||||
|
password.as_bytes().as_ptr(),
|
||||||
|
password.as_bytes().len() as u64,
|
||||||
|
salt.as_ptr() as *const [u8; crypto_pwhash_scryptsalsa208sha256_SALTBYTES],
|
||||||
|
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE as u64,
|
||||||
|
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
|
||||||
|
) };
|
||||||
|
if res != 0 {
|
||||||
|
panic!("Key derivation failed");
|
||||||
|
}
|
||||||
|
match method {
|
||||||
|
CryptoMethod::ChaCha20 => {
|
||||||
|
let mut crypto_key = [0; crypto_aead_chacha20poly1305_KEYBYTES];
|
||||||
|
for i in 0..crypto_key.len() {
|
||||||
|
crypto_key[i] = key[i];
|
||||||
|
}
|
||||||
|
let mut nonce = [0u8; crypto_aead_chacha20poly1305_NPUBBYTES];
|
||||||
|
unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) };
|
||||||
|
Crypto::ChaCha20Poly1305{key: crypto_key, nonce: nonce}
|
||||||
|
},
|
||||||
|
CryptoMethod::AES256 => {
|
||||||
|
let mut crypto_key = [0; crypto_aead_aes256gcm_KEYBYTES];
|
||||||
|
for i in 0..crypto_key.len() {
|
||||||
|
crypto_key[i] = key[i];
|
||||||
|
}
|
||||||
|
let mut nonce = [0u8; crypto_aead_aes256gcm_NPUBBYTES];
|
||||||
|
unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) };
|
||||||
|
Crypto::AES256GCM{key: crypto_key, nonce: nonce}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt(&self, mut buf: &mut [u8], nonce: &[u8], header: &[u8]) -> Result<usize, Error> {
|
||||||
|
match self {
|
||||||
|
&Crypto::None => Ok(buf.len()),
|
||||||
|
&Crypto::ChaCha20Poly1305{ref key, nonce: _} => {
|
||||||
|
let mut mlen: u64 = buf.len() as u64;
|
||||||
|
let res = unsafe { crypto_aead_chacha20poly1305_decrypt(
|
||||||
|
buf.as_mut_ptr(), // Base pointer to buffer
|
||||||
|
&mut mlen, // Mutable size of buffer (will be set to used size)
|
||||||
|
ptr::null_mut::<[u8; 0]>(), // Mutable base pointer to secret nonce (always NULL)
|
||||||
|
buf.as_ptr(), // Base pointer to message
|
||||||
|
buf.len() as u64, // Size of message
|
||||||
|
header.as_ptr(), // Base pointer to additional data
|
||||||
|
header.len() as u64, // Size of additional data
|
||||||
|
nonce.as_ptr() as *const [u8; 8], // Base pointer to public nonce
|
||||||
|
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
||||||
|
) };
|
||||||
|
match res {
|
||||||
|
0 => Ok(mlen as usize),
|
||||||
|
_ => Err(Error::CryptoError("Failed to decrypt"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&Crypto::AES256GCM{ref key, nonce: _} => {
|
||||||
|
let mut mlen: u64 = buf.len() as u64;
|
||||||
|
let res = unsafe { crypto_aead_aes256gcm_decrypt(
|
||||||
|
buf.as_mut_ptr(), // Base pointer to buffer
|
||||||
|
&mut mlen, // Mutable size of buffer (will be set to used size)
|
||||||
|
ptr::null_mut::<[u8; 0]>(), // Mutable base pointer to secret nonce (always NULL)
|
||||||
|
buf.as_ptr(), // Base pointer to message
|
||||||
|
buf.len() as u64, // Size of message
|
||||||
|
header.as_ptr(), // Base pointer to additional data
|
||||||
|
header.len() as u64, // Size of additional data
|
||||||
|
nonce.as_ptr() as *const [u8; 12], // Base pointer to public nonce
|
||||||
|
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
||||||
|
) };
|
||||||
|
match res {
|
||||||
|
0 => Ok(mlen as usize),
|
||||||
|
_ => Err(Error::CryptoError("Failed to decrypt"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encrypt(&mut self, mut buf: &mut [u8], mlen: usize, nonce_bytes: &mut [u8], header: &[u8]) -> usize {
|
||||||
|
match self {
|
||||||
|
&mut Crypto::None => mlen,
|
||||||
|
&mut Crypto::ChaCha20Poly1305{ref key, ref mut nonce} => {
|
||||||
|
inc_nonce_8(nonce);
|
||||||
|
let mut clen: u64 = buf.len() as u64;
|
||||||
|
assert_eq!(nonce_bytes.len(), nonce.len());
|
||||||
|
assert_eq!(nonce.len(), crypto_aead_chacha20poly1305_NPUBBYTES);
|
||||||
|
assert_eq!(key.len(), crypto_aead_chacha20poly1305_KEYBYTES);
|
||||||
|
assert_eq!(0, crypto_aead_chacha20poly1305_NSECBYTES);
|
||||||
|
assert!(clen as usize >= mlen + crypto_aead_chacha20poly1305_ABYTES);
|
||||||
|
let res = unsafe { crypto_aead_chacha20poly1305_encrypt(
|
||||||
|
buf.as_mut_ptr(), // Base pointer to buffer
|
||||||
|
&mut clen, // Mutable size of buffer (will be set to used size)
|
||||||
|
buf.as_ptr(), // Base pointer to message
|
||||||
|
mlen as u64, // Size of message
|
||||||
|
header.as_ptr(), // Base pointer to additional data
|
||||||
|
header.len() as u64, // Size of additional data
|
||||||
|
ptr::null::<[u8; 0]>(), // Base pointer to secret nonce (always NULL)
|
||||||
|
nonce.as_ptr() as *const [u8; 8], // Base pointer to public nonce
|
||||||
|
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
||||||
|
) };
|
||||||
|
assert_eq!(res, 0);
|
||||||
|
assert_eq!(clen as usize, mlen + crypto_aead_chacha20poly1305_ABYTES);
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(nonce.as_ptr(), nonce_bytes.as_mut_ptr(), nonce.len());
|
||||||
|
}
|
||||||
|
clen as usize
|
||||||
|
},
|
||||||
|
&mut Crypto::AES256GCM{ref key, ref mut nonce} => {
|
||||||
|
inc_nonce_12(nonce);
|
||||||
|
let mut clen: u64 = buf.len() as u64;
|
||||||
|
assert_eq!(nonce_bytes.len(), nonce.len());
|
||||||
|
assert_eq!(nonce.len(), crypto_aead_aes256gcm_NPUBBYTES);
|
||||||
|
assert_eq!(key.len(), crypto_aead_aes256gcm_KEYBYTES);
|
||||||
|
assert_eq!(0, crypto_aead_aes256gcm_NSECBYTES);
|
||||||
|
assert!(clen as usize >= mlen + crypto_aead_aes256gcm_ABYTES);
|
||||||
|
let res = unsafe { crypto_aead_aes256gcm_encrypt(
|
||||||
|
buf.as_mut_ptr(), // Base pointer to buffer
|
||||||
|
&mut clen, // Mutable size of buffer (will be set to used size)
|
||||||
|
buf.as_ptr(), // Base pointer to message
|
||||||
|
mlen as u64, // Size of message
|
||||||
|
header.as_ptr(), // Base pointer to additional data
|
||||||
|
header.len() as u64, // Size of additional data
|
||||||
|
ptr::null::<[u8; 0]>(), // Base pointer to secret nonce (always NULL)
|
||||||
|
nonce.as_ptr() as *const [u8; 12], // Base pointer to public nonce
|
||||||
|
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
||||||
|
) };
|
||||||
|
assert_eq!(res, 0);
|
||||||
|
assert_eq!(clen as usize, mlen + crypto_aead_aes256gcm_ABYTES);
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(nonce.as_ptr(), nonce_bytes.as_mut_ptr(), nonce.len());
|
||||||
|
}
|
||||||
|
clen as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
use super::super::types::Error;
|
|
||||||
|
|
||||||
pub enum Crypto {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Crypto {
|
|
||||||
pub fn init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn method(&self) -> u8 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nonce_bytes(&self) -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn additional_bytes(&self) -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_shared_key(_password: &str) -> Self {
|
|
||||||
panic!("This binary has no crypto support");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrypt(&self, mut _buf: &mut [u8], _nonce: &[u8], _hash: &[u8]) -> Result<usize, Error> {
|
|
||||||
unreachable!("This should never be called")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encrypt(&mut self, mut _buf: &mut [u8], _mlen: usize, _nonce_bytes: &mut [u8], _header: &[u8]) -> usize {
|
|
||||||
unreachable!("This should never be called")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
#[cfg(feature = "crypto")] mod sodium;
|
|
||||||
#[cfg(not(feature = "crypto"))] mod dummy;
|
|
||||||
|
|
||||||
#[cfg(feature = "crypto")] pub use self::sodium::Crypto;
|
|
||||||
#[cfg(not(feature = "crypto"))] pub use self::dummy::Crypto;
|
|
|
@ -1,151 +0,0 @@
|
||||||
use std::{mem, ptr};
|
|
||||||
|
|
||||||
use libsodium_sys::*;
|
|
||||||
|
|
||||||
use super::super::types::Error;
|
|
||||||
|
|
||||||
pub enum Crypto {
|
|
||||||
None,
|
|
||||||
ChaCha20Poly1305{key: [u8; 32], nonce: [u8; 8]}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inc_nonce(nonce: [u8; 8]) -> [u8; 8] {
|
|
||||||
unsafe {
|
|
||||||
let mut num: u64 = mem::transmute(nonce);
|
|
||||||
num = num.wrapping_add(1);
|
|
||||||
mem::transmute(num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Crypto {
|
|
||||||
pub fn init() {
|
|
||||||
unsafe { sodium_init() };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn method(&self) -> u8 {
|
|
||||||
match self {
|
|
||||||
&Crypto::None => 0,
|
|
||||||
&Crypto::ChaCha20Poly1305{key: _, nonce: _} => 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nonce_bytes(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
&Crypto::None => 0,
|
|
||||||
&Crypto::ChaCha20Poly1305{key: _, ref nonce} => nonce.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn additional_bytes(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
&Crypto::None => 0,
|
|
||||||
&Crypto::ChaCha20Poly1305{key: _, nonce: _} => crypto_aead_chacha20poly1305_ABYTES
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_shared_key(password: &str) -> Self {
|
|
||||||
|
|
||||||
let salt = "vpncloudVPNCLOUDvpncl0udVpnCloud".as_bytes();
|
|
||||||
assert_eq!(salt.len(), crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
|
||||||
let mut key = [0; crypto_pwhash_scryptsalsa208sha256_STRBYTES];
|
|
||||||
let res = unsafe { crypto_pwhash_scryptsalsa208sha256(
|
|
||||||
key.as_mut_ptr(),
|
|
||||||
key.len() as u64,
|
|
||||||
password.as_bytes().as_ptr(),
|
|
||||||
password.as_bytes().len() as u64,
|
|
||||||
salt.as_ptr() as *const [u8; crypto_pwhash_scryptsalsa208sha256_SALTBYTES],
|
|
||||||
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE as u64,
|
|
||||||
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
|
|
||||||
) };
|
|
||||||
if res != 0 {
|
|
||||||
panic!("Key derivation failed");
|
|
||||||
}
|
|
||||||
let mut crypto_key = [0; 32];
|
|
||||||
for i in 0..crypto_key.len() {
|
|
||||||
crypto_key[i] = key[i];
|
|
||||||
}
|
|
||||||
let mut nonce = [0u8; 8];
|
|
||||||
unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) };
|
|
||||||
Crypto::ChaCha20Poly1305{key: crypto_key, nonce: nonce}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrypt(&self, mut buf: &mut [u8], nonce: &[u8], header: &[u8]) -> Result<usize, Error> {
|
|
||||||
match self {
|
|
||||||
&Crypto::None => Ok(buf.len()),
|
|
||||||
&Crypto::ChaCha20Poly1305{ref key, nonce: _} => {
|
|
||||||
let mut mlen: u64 = buf.len() as u64;
|
|
||||||
let res = unsafe { crypto_aead_chacha20poly1305_decrypt(
|
|
||||||
buf.as_mut_ptr(), // Base pointer to buffer
|
|
||||||
&mut mlen, // Mutable size of buffer (will be set to used size)
|
|
||||||
ptr::null_mut::<[u8; 0]>(), // Mutable base pointer to secret nonce (always NULL)
|
|
||||||
buf.as_ptr(), // Base pointer to message
|
|
||||||
buf.len() as u64, // Size of message
|
|
||||||
header.as_ptr(), // Base pointer to additional data
|
|
||||||
header.len() as u64, // Size of additional data
|
|
||||||
nonce.as_ptr() as *const [u8; 8], // Base pointer to public nonce
|
|
||||||
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
|
||||||
) };
|
|
||||||
match res {
|
|
||||||
0 => Ok(mlen as usize),
|
|
||||||
_ => Err(Error::CryptoError("Failed to decrypt"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encrypt(&mut self, mut buf: &mut [u8], mlen: usize, nonce_bytes: &mut [u8], header: &[u8]) -> usize {
|
|
||||||
match self {
|
|
||||||
&mut Crypto::None => mlen,
|
|
||||||
&mut Crypto::ChaCha20Poly1305{ref key, ref mut nonce} => {
|
|
||||||
*nonce = inc_nonce(*nonce);
|
|
||||||
let mut clen: u64 = buf.len() as u64;
|
|
||||||
assert_eq!(nonce_bytes.len(), nonce.len());
|
|
||||||
assert_eq!(nonce.len(), crypto_aead_chacha20poly1305_NPUBBYTES);
|
|
||||||
assert_eq!(key.len(), crypto_aead_chacha20poly1305_KEYBYTES);
|
|
||||||
assert_eq!(0, crypto_aead_chacha20poly1305_NSECBYTES);
|
|
||||||
assert!(clen as usize >= mlen + crypto_aead_chacha20poly1305_ABYTES);
|
|
||||||
let res = unsafe { crypto_aead_chacha20poly1305_encrypt(
|
|
||||||
buf.as_mut_ptr(), // Base pointer to buffer
|
|
||||||
&mut clen, // Mutable size of buffer (will be set to used size)
|
|
||||||
buf.as_ptr(), // Base pointer to message
|
|
||||||
mlen as u64, // Size of message
|
|
||||||
header.as_ptr(), // Base pointer to additional data
|
|
||||||
header.len() as u64, // Size of additional data
|
|
||||||
ptr::null::<[u8; 0]>(), // Base pointer to secret nonce (always NULL)
|
|
||||||
nonce.as_ptr() as *const [u8; 8], // Base pointer to public nonce
|
|
||||||
key.as_ptr() as *const [u8; 32] // Base pointer to key
|
|
||||||
) };
|
|
||||||
assert_eq!(res, 0);
|
|
||||||
assert_eq!(clen as usize, mlen + crypto_aead_chacha20poly1305_ABYTES);
|
|
||||||
unsafe {
|
|
||||||
ptr::copy_nonoverlapping(nonce.as_ptr(), nonce_bytes.as_mut_ptr(), nonce.len());
|
|
||||||
}
|
|
||||||
clen as usize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn encrypt_decrypt() {
|
|
||||||
let mut sender = Crypto::from_shared_key("test");
|
|
||||||
let receiver = Crypto::from_shared_key("test");
|
|
||||||
let msg = "HelloWorld0123456789";
|
|
||||||
let msg_bytes = msg.as_bytes();
|
|
||||||
let mut buffer = [0u8; 1024];
|
|
||||||
let header = [0u8; 8];
|
|
||||||
for i in 0..msg_bytes.len() {
|
|
||||||
buffer[i] = msg_bytes[i];
|
|
||||||
}
|
|
||||||
let mut nonce1 = [0u8; 8];
|
|
||||||
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce1, &header);
|
|
||||||
assert_eq!(size, msg_bytes.len() + sender.additional_bytes());
|
|
||||||
assert!(msg_bytes != &buffer[..msg_bytes.len()] as &[u8]);
|
|
||||||
receiver.decrypt(&mut buffer[..size], &nonce1, &header).unwrap();
|
|
||||||
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
|
||||||
let mut nonce2 = [0u8; 8];
|
|
||||||
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce2, &header);
|
|
||||||
assert!(nonce1 != nonce2);
|
|
||||||
receiver.decrypt(&mut buffer[..size], &nonce2, &header).unwrap();
|
|
||||||
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
|
||||||
}
|
|
11
src/main.rs
11
src/main.rs
|
@ -7,7 +7,6 @@ extern crate epoll;
|
||||||
extern crate signal;
|
extern crate signal;
|
||||||
extern crate nix;
|
extern crate nix;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
#[cfg(feature = "crypto")] extern crate libsodium_sys;
|
|
||||||
#[cfg(feature = "bench")] extern crate test;
|
#[cfg(feature = "bench")] extern crate test;
|
||||||
|
|
||||||
#[macro_use] mod util;
|
#[macro_use] mod util;
|
||||||
|
@ -33,7 +32,7 @@ use ip::RoutingTable;
|
||||||
use types::{Error, Mode, Type, Range, Table, Protocol};
|
use types::{Error, Mode, Type, Range, Table, Protocol};
|
||||||
use cloud::GenericCloud;
|
use cloud::GenericCloud;
|
||||||
use udpmessage::VERSION;
|
use udpmessage::VERSION;
|
||||||
use crypto::Crypto;
|
use crypto::{Crypto, CryptoMethod};
|
||||||
use util::Duration;
|
use util::Duration;
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,6 +59,7 @@ struct Args {
|
||||||
flag_type: Type,
|
flag_type: Type,
|
||||||
flag_mode: Mode,
|
flag_mode: Mode,
|
||||||
flag_shared_key: Option<String>,
|
flag_shared_key: Option<String>,
|
||||||
|
flag_crypto: CryptoMethod,
|
||||||
flag_subnet: Vec<String>,
|
flag_subnet: Vec<String>,
|
||||||
flag_device: String,
|
flag_device: String,
|
||||||
flag_listen: String,
|
flag_listen: String,
|
||||||
|
@ -113,7 +113,7 @@ fn run<T: Protocol> (args: Args) {
|
||||||
});
|
});
|
||||||
Crypto::init();
|
Crypto::init();
|
||||||
let crypto = match args.flag_shared_key {
|
let crypto = match args.flag_shared_key {
|
||||||
Some(key) => Crypto::from_shared_key(&key),
|
Some(key) => Crypto::from_shared_key(args.flag_crypto, &key),
|
||||||
None => Crypto::None
|
None => Crypto::None
|
||||||
};
|
};
|
||||||
let mut cloud = GenericCloud::<T>::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges, crypto);
|
let mut cloud = GenericCloud::<T>::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges, crypto);
|
||||||
|
@ -132,9 +132,8 @@ fn run<T: Protocol> (args: Args) {
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
|
let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
|
||||||
if args.flag_version {
|
if args.flag_version {
|
||||||
println!("VpnCloud v{} ({}, protocol version {})", env!("CARGO_PKG_VERSION"),
|
println!("VpnCloud v{} (protocol version {}, libsodium {})", env!("CARGO_PKG_VERSION"),
|
||||||
if cfg!(feature = "crypto") { "with crypto support" } else { "without crypto support" },
|
VERSION, Crypto::sodium_version()
|
||||||
VERSION
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
57
src/tests.rs
57
src/tests.rs
|
@ -5,7 +5,7 @@ use super::ethernet::{Frame, SwitchTable};
|
||||||
use super::ip::{RoutingTable, Packet};
|
use super::ip::{RoutingTable, Packet};
|
||||||
use super::types::{Protocol, Address, Range, Table};
|
use super::types::{Protocol, Address, Range, Table};
|
||||||
use super::udpmessage::{Options, Message, decode, encode};
|
use super::udpmessage::{Options, Message, decode, encode};
|
||||||
use super::crypto::Crypto;
|
use super::crypto::{Crypto, CryptoMethod};
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -23,11 +23,10 @@ fn udpmessage_packet() {
|
||||||
assert_eq!(msg, msg2);
|
assert_eq!(msg, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "crypto")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn udpmessage_encrypted() {
|
fn udpmessage_encrypted() {
|
||||||
let mut options = Options::default();
|
let mut options = Options::default();
|
||||||
let mut crypto = Crypto::from_shared_key("test");
|
let mut crypto = Crypto::from_shared_key(CryptoMethod::ChaCha20, "test");
|
||||||
let payload = [1,2,3,4,5];
|
let payload = [1,2,3,4,5];
|
||||||
let msg = Message::Data(&payload);
|
let msg = Message::Data(&payload);
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
|
@ -122,11 +121,9 @@ fn udpmessage_invalid() {
|
||||||
assert!(decode(&mut [0x76,0x70,0x6e,1,0,0,1,0], &mut crypto).is_err());
|
assert!(decode(&mut [0x76,0x70,0x6e,1,0,0,1,0], &mut crypto).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "crypto")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn udpmessage_invalid_crypto() {
|
fn udpmessage_invalid_crypto() {
|
||||||
let mut options = Options::default();
|
let mut crypto = Crypto::from_shared_key(CryptoMethod::ChaCha20, "test");
|
||||||
let mut crypto = Crypto::from_shared_key("test");
|
|
||||||
// truncated crypto
|
// truncated crypto
|
||||||
assert!(decode(&mut [0x76,0x70,0x6e,1,1,0,0,0], &mut crypto).is_err());
|
assert!(decode(&mut [0x76,0x70,0x6e,1,1,0,0,0], &mut crypto).is_err());
|
||||||
}
|
}
|
||||||
|
@ -252,3 +249,51 @@ fn message_fmt() {
|
||||||
])), "Init(stage=0, [0.1.2.3/24, 00:01:02:03:04:05/16])");
|
])), "Init(stage=0, [0.1.2.3/24, 00:01:02:03:04:05/16])");
|
||||||
assert_eq!(format!("{:?}", Message::Close), "Close");
|
assert_eq!(format!("{:?}", Message::Close), "Close");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn encrypt_decrypt_chacha20poly1305() {
|
||||||
|
let mut sender = Crypto::from_shared_key(CryptoMethod::ChaCha20, "test");
|
||||||
|
let receiver = Crypto::from_shared_key(CryptoMethod::ChaCha20, "test");
|
||||||
|
let msg = "HelloWorld0123456789";
|
||||||
|
let msg_bytes = msg.as_bytes();
|
||||||
|
let mut buffer = [0u8; 1024];
|
||||||
|
let header = [0u8; 8];
|
||||||
|
for i in 0..msg_bytes.len() {
|
||||||
|
buffer[i] = msg_bytes[i];
|
||||||
|
}
|
||||||
|
let mut nonce1 = [0u8; 8];
|
||||||
|
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce1, &header);
|
||||||
|
assert_eq!(size, msg_bytes.len() + sender.additional_bytes());
|
||||||
|
assert!(msg_bytes != &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
receiver.decrypt(&mut buffer[..size], &nonce1, &header).unwrap();
|
||||||
|
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
let mut nonce2 = [0u8; 8];
|
||||||
|
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce2, &header);
|
||||||
|
assert!(nonce1 != nonce2);
|
||||||
|
receiver.decrypt(&mut buffer[..size], &nonce2, &header).unwrap();
|
||||||
|
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn encrypt_decrypt_aes256() {
|
||||||
|
let mut sender = Crypto::from_shared_key(CryptoMethod::AES256, "test");
|
||||||
|
let receiver = Crypto::from_shared_key(CryptoMethod::AES256, "test");
|
||||||
|
let msg = "HelloWorld0123456789";
|
||||||
|
let msg_bytes = msg.as_bytes();
|
||||||
|
let mut buffer = [0u8; 1024];
|
||||||
|
let header = [0u8; 8];
|
||||||
|
for i in 0..msg_bytes.len() {
|
||||||
|
buffer[i] = msg_bytes[i];
|
||||||
|
}
|
||||||
|
let mut nonce1 = [0u8; 8];
|
||||||
|
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce1, &header);
|
||||||
|
assert_eq!(size, msg_bytes.len() + sender.additional_bytes());
|
||||||
|
assert!(msg_bytes != &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
receiver.decrypt(&mut buffer[..size], &nonce1, &header).unwrap();
|
||||||
|
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
let mut nonce2 = [0u8; 8];
|
||||||
|
let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce2, &header);
|
||||||
|
assert!(nonce1 != nonce2);
|
||||||
|
receiver.decrypt(&mut buffer[..size], &nonce2, &header).unwrap();
|
||||||
|
assert_eq!(msg_bytes, &buffer[..msg_bytes.len()] as &[u8]);
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ Options:
|
||||||
--subnet <subnet> The local subnets to use.
|
--subnet <subnet> The local subnets to use.
|
||||||
--network-id <id> Optional token that identifies the network.
|
--network-id <id> Optional token that identifies the network.
|
||||||
--shared-key <key> The shared key to encrypt all traffic.
|
--shared-key <key> The shared key to encrypt all traffic.
|
||||||
|
--crypto <method> The encryption method to use ("aes256", or
|
||||||
|
"chacha20"). [default: aes256]
|
||||||
--peer-timeout <secs> Peer timeout in seconds. [default: 1800]
|
--peer-timeout <secs> Peer timeout in seconds. [default: 1800]
|
||||||
--dst-timeout <secs> Switch table entry timeout in seconds.
|
--dst-timeout <secs> Switch table entry timeout in seconds.
|
||||||
[default: 300]
|
[default: 300]
|
||||||
|
|
12
vpncloud.md
12
vpncloud.md
|
@ -49,6 +49,13 @@ vpncloud(1) -- Peer-to-peer VPN
|
||||||
An optional shared key to encrypt the VPN data. If this option is not set,
|
An optional shared key to encrypt the VPN data. If this option is not set,
|
||||||
the traffic will be sent unencrypted.
|
the traffic will be sent unencrypted.
|
||||||
|
|
||||||
|
* `--crypto <method>`:
|
||||||
|
|
||||||
|
The encryption method to use ("aes256", or "chacha20"). Most current CPUs
|
||||||
|
have special support for AES256 so this should be faster. For older
|
||||||
|
computers lacking this support, CHACHA20 should be faster.
|
||||||
|
[default: `aes256`]
|
||||||
|
|
||||||
* `--network-id <id>`:
|
* `--network-id <id>`:
|
||||||
|
|
||||||
An optional token that identifies the network and helps to distinguish it
|
An optional token that identifies the network and helps to distinguish it
|
||||||
|
@ -233,6 +240,11 @@ Every packet sent over UDP contains the following header (in order):
|
||||||
`libsodium::crypto_aead_chacha20poly1305` method, using the 8 byte header
|
`libsodium::crypto_aead_chacha20poly1305` method, using the 8 byte header
|
||||||
as additional data.
|
as additional data.
|
||||||
|
|
||||||
|
- Method `2`, **AES256GCM**: The header is followed by a 12 byte *nonce*.
|
||||||
|
The rest of the data is encrypted with the
|
||||||
|
`libsodium::crypto_aead_aes256gcm` method, using the 8 byte header
|
||||||
|
as additional data.
|
||||||
|
|
||||||
* 1 `reserved byte` that is currently unused
|
* 1 `reserved byte` that is currently unused
|
||||||
|
|
||||||
* 1 byte for `flags`
|
* 1 byte for `flags`
|
||||||
|
|
Loading…
Reference in New Issue