diff --git a/Cargo.lock b/Cargo.lock index f8294be..5ced9b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,16 +6,6 @@ dependencies = [ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "aligned_alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "arrayvec" version = "0.4.10" @@ -574,6 +564,17 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ring" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -938,6 +939,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "untrusted" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "utf8-ranges" version = "1.0.2" @@ -957,7 +963,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "vpncloud" version = "0.8.2" dependencies = [ - "aligned_alloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -969,6 +974,7 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1052,7 +1058,6 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" -"checksum aligned_alloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9dcebfb002ccde769c15bc841d0d5548a90e80fcd2ffed5131339e8074746f0a" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1118,6 +1123,7 @@ dependencies = [ "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" +"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" @@ -1158,6 +1164,7 @@ dependencies = [ "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 4bd3209..da4f22d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ serde_yaml = "0.8" log = { version = "0.4", features = ["std"] } signal = "0.6" libc = "0.2" -aligned_alloc = "0.1" rand = "0.6" fnv = "1" net2 = "0.2" @@ -28,6 +27,7 @@ yaml-rust = "0.4" igd = "0.7" siphasher = "0.3" daemonize = "0.3" +ring = "0.13" [build-dependencies] cc = "^1" diff --git a/src/crypto.rs b/src/crypto.rs index 2eaf37a..6420adc 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -5,11 +5,11 @@ 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 aligned_alloc::{aligned_alloc, aligned_free}; use super::types::Error; @@ -42,22 +42,6 @@ const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: usize = 524_288; #[allow(non_upper_case_globals)] const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16_777_216; -pub struct Aes256State(*mut [u8; crypto_aead_aes256gcm_STATEBYTES]); - -impl Aes256State { - fn new() -> Aes256State { - let ptr = aligned_alloc(crypto_aead_aes256gcm_STATEBYTES, 16) - as *mut [u8; crypto_aead_aes256gcm_STATEBYTES]; - Aes256State(ptr) - } -} - -impl Drop for Aes256State { - fn drop(&mut self) { - unsafe { aligned_free(self.0 as *mut ()) } - } -} - #[link(name="sodium", kind="static")] extern { @@ -127,23 +111,24 @@ pub enum CryptoMethod { AES256 } -pub enum Crypto { - None, - ChaCha20Poly1305{ - key: [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES], - nonce: [u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES] - }, - AES256GCM{ - state: Aes256State, - nonce: [u8; crypto_aead_aes256gcm_NPUBBYTES] - } +pub struct CryptoData { + sealing_key: SealingKey, + opening_key: OpeningKey, + nonce: Vec } -fn inc_nonce_12(nonce: &mut [u8; 12]) { - for i in 0..12 { - let mut num = nonce[11-i]; +pub enum Crypto { + None, + ChaCha20Poly1305(CryptoData), + AES256GCM(CryptoData) +} + +fn inc_nonce(nonce: &mut [u8]) { + let l = nonce.len(); + for i in (0..l).rev() { + let mut num = nonce[i]; num = num.wrapping_add(1); - nonce[11-i] = num; + nonce[i] = num; if num > 0 { break } @@ -170,9 +155,7 @@ impl Crypto { #[inline] pub fn aes256_available() -> bool { - unsafe { - crypto_aead_aes256gcm_is_available() == 1 - } + true } #[inline] @@ -188,7 +171,7 @@ impl Crypto { pub fn nonce_bytes(&self) -> usize { match *self { Crypto::None => 0, - Crypto::ChaCha20Poly1305{ref nonce, ..} | Crypto::AES256GCM{ref nonce, ..} => nonce.len(), + Crypto::ChaCha20Poly1305(ref data) | Crypto::AES256GCM(ref data) => data.sealing_key.algorithm().nonce_len() } } @@ -218,69 +201,30 @@ impl Crypto { if res != 0 { fail!("Key derivation failed"); } + let algo = match method { + CryptoMethod::ChaCha20 => &CHACHA20_POLY1305, + CryptoMethod::AES256 => &AES_256_GCM + }; + 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()) }; + let data = CryptoData { sealing_key, opening_key, nonce }; match method { - CryptoMethod::ChaCha20 => { - let mut crypto_key = [0; crypto_aead_chacha20poly1305_ietf_KEYBYTES]; - crypto_key.clone_from_slice(&key[..crypto_aead_chacha20poly1305_ietf_KEYBYTES]); - let mut nonce = [0u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; - unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) }; - Crypto::ChaCha20Poly1305{key: crypto_key, nonce} - }, - CryptoMethod::AES256 => { - if ! Crypto::aes256_available() { - fail!("AES256 is not supported by this processor, use ChaCha20 instead"); - } - let mut nonce = [0u8; crypto_aead_aes256gcm_NPUBBYTES]; - unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) }; - let state = Aes256State::new(); - let res = unsafe { crypto_aead_aes256gcm_beforenm( - state.0, - key[..crypto_aead_aes256gcm_KEYBYTES].as_ptr() as *const [u8; crypto_aead_aes256gcm_KEYBYTES] - ) }; - assert_eq!(res, 0); - Crypto::AES256GCM{state, nonce} - } + CryptoMethod::ChaCha20 => Crypto::ChaCha20Poly1305(data), + CryptoMethod::AES256 => Crypto::AES256GCM(data) } } pub fn decrypt(&self, buf: &mut [u8], nonce: &[u8], header: &[u8]) -> Result { match *self { Crypto::None => Ok(buf.len()), - Crypto::ChaCha20Poly1305{ref key, ..} => { - let mut mlen: u64 = buf.len() as u64; - let res = unsafe { crypto_aead_chacha20poly1305_ietf_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; crypto_aead_chacha20poly1305_ietf_NPUBBYTES], // Base pointer to public nonce - key.as_ptr() as *const [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES] // Base pointer to key - ) }; - match res { - 0 => Ok(mlen as usize), - _ => Err(Error::Crypto("Failed to decrypt")) - } - }, - Crypto::AES256GCM{ref state, ..} => { - let mut mlen: u64 = buf.len() as u64; - let res = unsafe { crypto_aead_aes256gcm_decrypt_afternm( - 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; crypto_aead_aes256gcm_NPUBBYTES], // Base pointer to public nonce - state.0 // Base pointer to state - ) }; - match res { - 0 => Ok(mlen as usize), - _ => Err(Error::Crypto("Failed to decrypt")) - } + 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()) } } } @@ -288,49 +232,16 @@ impl Crypto { pub fn encrypt(&mut self, buf: &mut [u8], mlen: usize, nonce_bytes: &mut [u8], header: &[u8]) -> usize { match *self { Crypto::None => mlen, - Crypto::ChaCha20Poly1305{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!(clen as usize >= mlen + crypto_aead_chacha20poly1305_ietf_ABYTES); - let res = unsafe { crypto_aead_chacha20poly1305_ietf_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; crypto_aead_chacha20poly1305_ietf_NPUBBYTES], // Base pointer to public nonce - key.as_ptr() as *const [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES] // Base pointer to key - ) }; - assert_eq!(res, 0); + 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(nonce.as_ptr(), nonce_bytes.as_mut_ptr(), nonce.len()); + ptr::copy_nonoverlapping(data.nonce.as_ptr(), nonce_bytes.as_mut_ptr(), data.nonce.len()); } - clen as usize - }, - Crypto::AES256GCM{ref state, ref mut nonce} => { - inc_nonce_12(nonce); - let mut clen: u64 = buf.len() as u64; - assert_eq!(nonce_bytes.len(), nonce.len()); - assert!(clen as usize >= mlen + crypto_aead_aes256gcm_ABYTES); - let res = unsafe { crypto_aead_aes256gcm_encrypt_afternm( - 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; crypto_aead_aes256gcm_NPUBBYTES], // Base pointer to public nonce - state.0 // Base pointer to state - ) }; - assert_eq!(res, 0); - unsafe { - ptr::copy_nonoverlapping(nonce.as_ptr(), nonce_bytes.as_mut_ptr(), nonce.len()); - } - clen as usize + new_len } } } diff --git a/src/main.rs b/src/main.rs index 2670cec..be04ffc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ extern crate serde; extern crate serde_yaml; extern crate signal; extern crate libc; -extern crate aligned_alloc; extern crate rand; extern crate fnv; extern crate net2; @@ -21,6 +20,7 @@ extern crate yaml_rust; extern crate igd; extern crate siphasher; extern crate daemonize; +extern crate ring; #[cfg(feature = "bench")] extern crate test; #[macro_use] pub mod util;