From 6a3208949e1d8c9d3b17386d12164c0925b0c2ea Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Tue, 8 Jan 2019 20:32:47 +0100 Subject: [PATCH] Removed libsodium completely --- .gitmodules | 3 - Makefile | 3 - build.rs | 35 ------------ libsodium | 1 - src/crypto.rs | 154 ++++++++------------------------------------------ 5 files changed, 24 insertions(+), 172 deletions(-) delete mode 100644 .gitmodules delete mode 160000 libsodium diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e11a73b..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "libsodium"] - path = libsodium - url = https://github.com/jedisct1/libsodium diff --git a/Makefile b/Makefile index 0b8a18b..137bfe4 100644 --- a/Makefile +++ b/Makefile @@ -3,17 +3,14 @@ default: test build .PHONY: build build: - git submodule update --init cargo build --release .PHONY: test test: - git submodule update --init cargo test .PHONY: bench bench: - git submodule update --init cargo bench --features bench .PHONY: deb diff --git a/build.rs b/build.rs index b7a5e8f..11687a3 100644 --- a/build.rs +++ b/build.rs @@ -3,42 +3,7 @@ // This software is licensed under GPL-3 or newer (see LICENSE.md) extern crate cc; -extern crate pkg_config; - -use std::process::Command; -use std::path::PathBuf; -use std::env; -use std::fs; fn main() { cc::Build::new().file("src/c/tuntap.c").include("src").compile("libtuntap.a"); - if cfg!(feature = "system-libsodium") { - pkg_config::Config::new().atleast_version("1.0.8").probe("libsodium").expect("Libsodium >= 1.0.8 missing"); - return - } else { - let target = env::var("TARGET").unwrap(); - let dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let libsodium_dir = dir.join("libsodium"); - let libsodium_target_dir = dir.join("target/sodium-build").join(&target); - let libsodium_target_file = libsodium_target_dir.join("libsodium.a"); - if ! libsodium_target_file.exists() { - fs::create_dir_all(&libsodium_target_dir).unwrap(); - Command::new("make").arg("clean").current_dir(&libsodium_dir).status().unwrap(); - Command::new("sh").arg("autogen.sh").current_dir(&libsodium_dir).status().unwrap(); - let mut args = vec!["configure", "--host", &target]; - if target.starts_with("i686-") { - args.extend(vec!["CFLAGS=-m32", "CXXFLAGS=-m32", "LDFLAGS=-m32"]); - } - if target.ends_with("-musl") { - args.extend(vec!["CC=musl-gcc"]); - } - if target == "arm-unknown-linux-gnueabihf" || target == "armv7-unknown-linux-gnueabihf" { - args.extend(vec!["CC=arm-linux-gnueabihf-gcc"]); - } - Command::new("sh").args(&args).current_dir(&libsodium_dir).status().unwrap(); - Command::new("make").current_dir(&libsodium_dir).status().unwrap(); - fs::copy(libsodium_dir.join("src/libsodium/.libs/libsodium.a"), libsodium_target_file).unwrap(); - } - println!("cargo:rustc-link-search={}", libsodium_target_dir.to_str().unwrap()); - } } diff --git a/libsodium b/libsodium deleted file mode 160000 index 675149b..0000000 --- a/libsodium +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 675149b9b8b66ff44152553fb3ebf9858128363d diff --git a/src/crypto.rs b/src/crypto.rs index 6420adc..c76fe3e 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -2,106 +2,13 @@ // Copyright (C) 2015-2017 Dennis Schwerdel // This software is licensed under GPL-3 or newer (see LICENSE.md) -use std::ptr; -use std::ffi::CStr; -use std::sync::{Once, ONCE_INIT}; use ring::aead::*; - -static CRYPTO_INIT: Once = ONCE_INIT; - -use libc::{size_t, c_char, c_ulonglong, c_int}; +use ring::pbkdf2; +use ring::rand::*; +use ring::digest::*; use super::types::Error; -#[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_ietf_KEYBYTES: usize = 32; -#[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_ietf_NSECBYTES: usize = 0; -#[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_ietf_NPUBBYTES: usize = 12; -#[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_ietf_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_aead_aes256gcm_STATEBYTES: usize = 512; - -#[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 = 524_288; -#[allow(non_upper_case_globals)] -const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16_777_216; - - -#[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_aead_aes256gcm_is_available() -> c_int; - 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_ietf_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_ietf_NSECBYTES], - npub: *const [u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES], - k: *const [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES]) -> c_int; - pub fn crypto_aead_chacha20poly1305_ietf_decrypt( - m: *mut u8, - mlen: *mut c_ulonglong, - nsec: *mut [u8; crypto_aead_chacha20poly1305_ietf_NSECBYTES], - c: *const u8, - clen: c_ulonglong, - ad: *const u8, - adlen: c_ulonglong, - npub: *const [u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES], - k: *const [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES]) -> c_int; - pub fn crypto_aead_aes256gcm_beforenm( - state: *mut [u8; crypto_aead_aes256gcm_STATEBYTES], - k: *const [u8; crypto_aead_aes256gcm_KEYBYTES]) -> c_int; - pub fn crypto_aead_aes256gcm_encrypt_afternm( - 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], - state: *const [u8; crypto_aead_aes256gcm_STATEBYTES]) -> c_int; - pub fn crypto_aead_aes256gcm_decrypt_afternm( - 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], - state: *const [u8; crypto_aead_aes256gcm_STATEBYTES]) -> c_int; -} - #[derive(Serialize, Deserialize, Debug, PartialEq)] pub enum CryptoMethod { @@ -117,6 +24,7 @@ pub struct CryptoData { nonce: Vec } +#[allow(unknown_lints, clippy::large_enum_variant)] pub enum Crypto { None, ChaCha20Poly1305(CryptoData), @@ -130,27 +38,21 @@ fn inc_nonce(nonce: &mut [u8]) { num = num.wrapping_add(1); nonce[i] = num; if num > 0 { - break + return } } + warn!("Nonce overflowed"); } impl Crypto { #[inline] pub fn init() { - CRYPTO_INIT.call_once(|| { - if unsafe { sodium_init() } != 0 { - fail!("Failed to initialize crypto library"); - } - }); } #[inline] pub fn sodium_version() -> String { - unsafe { - CStr::from_ptr(sodium_version_string()).to_string_lossy().to_string() - } + "0".to_string() } #[inline] @@ -180,38 +82,30 @@ impl Crypto { pub fn additional_bytes(&self) -> usize { match *self { Crypto::None => 0, - Crypto::ChaCha20Poly1305{..} => crypto_aead_chacha20poly1305_ietf_ABYTES, - Crypto::AES256GCM{..} => crypto_aead_aes256gcm_ABYTES + Crypto::ChaCha20Poly1305(ref data) | Crypto::AES256GCM(ref data) => data.sealing_key.algorithm().tag_len() } } pub fn from_shared_key(method: CryptoMethod, password: &str) -> Self { - let salt = b"vpncloudVPNCLOUDvpncl0udVpnCloud"; - 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 { - fail!("Key derivation failed"); - } let algo = match method { CryptoMethod::ChaCha20 => &CHACHA20_POLY1305, CryptoMethod::AES256 => &AES_256_GCM }; + let mut key: Vec = Vec::with_capacity(algo.key_len()); + for _ in 0..algo.key_len() { + key.push(0); + } + let salt = b"vpncloudVPNCLOUDvpncl0udVpnCloud"; + pbkdf2::derive(&SHA256, 4096, salt, password.as_bytes(), &mut key); let sealing_key = SealingKey::new(algo, &key[..algo.key_len()]).expect("Failed to create key"); let opening_key = OpeningKey::new(algo, &key[..algo.key_len()]).expect("Failed to create key"); let mut nonce: Vec = Vec::with_capacity(algo.nonce_len()); for _ in 0..algo.nonce_len() { nonce.push(0); } - unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) }; + if SystemRandom::new().fill(&mut nonce).is_err() { + fail!("Randomizing nonce failed"); + } let data = CryptoData { sealing_key, opening_key, nonce }; match method { CryptoMethod::ChaCha20 => Crypto::ChaCha20Poly1305(data), @@ -223,24 +117,24 @@ impl Crypto { match *self { Crypto::None => Ok(buf.len()), Crypto::ChaCha20Poly1305(ref data) | Crypto::AES256GCM(ref data) => { - let plaintext = open_in_place(&data.opening_key, nonce, header, 0, buf).expect("error"); - Ok(plaintext.len()) + match open_in_place(&data.opening_key, nonce, header, 0, buf) { + Ok(plaintext) => Ok(plaintext.len()), + Err(_) => Err(Error::Crypto("Failed to decrypt")) + } } } } pub fn encrypt(&mut self, buf: &mut [u8], mlen: usize, nonce_bytes: &mut [u8], header: &[u8]) -> usize { + let tag_len = self.additional_bytes(); match *self { Crypto::None => mlen, Crypto::ChaCha20Poly1305(ref mut data) | Crypto::AES256GCM(ref mut data) => { inc_nonce(&mut data.nonce); - let tag_len = data.sealing_key.algorithm().tag_len(); assert!(buf.len() - mlen >= tag_len); let buf = &mut buf[.. mlen + tag_len]; - let new_len = seal_in_place(&data.sealing_key, &data.nonce, header, buf, tag_len).expect("error"); - unsafe { - ptr::copy_nonoverlapping(data.nonce.as_ptr(), nonce_bytes.as_mut_ptr(), data.nonce.len()); - } + let new_len = seal_in_place(&data.sealing_key, &data.nonce, header, buf, tag_len).expect("Failed to encrypt"); + nonce_bytes.clone_from_slice(&data.nonce); new_len } }