From d8276fad58e86c31e568b46adb29aba14bb2c30a Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Tue, 1 Dec 2015 10:13:11 +0100 Subject: [PATCH] Using ietf chacha20 version and fixed crypto tests --- src/crypto.rs | 82 +++++++++++++++++++++++++++------------------------ src/tests.rs | 14 +++++---- vpncloud.md | 8 ++--- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/crypto.rs b/src/crypto.rs index 0ac02e9..df511f2 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,4 +1,4 @@ -use std::{mem, ptr}; +use std::ptr; use std::ffi::CStr; use libc::{size_t, c_char, c_ulonglong, c_int}; @@ -7,13 +7,13 @@ use aligned_alloc::{aligned_alloc, aligned_free}; use super::types::Error; #[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_KEYBYTES: usize = 32; +const crypto_aead_chacha20poly1305_ietf_KEYBYTES: usize = 32; #[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_NSECBYTES: usize = 0; +const crypto_aead_chacha20poly1305_ietf_NSECBYTES: usize = 0; #[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_NPUBBYTES: usize = 8; +const crypto_aead_chacha20poly1305_ietf_NPUBBYTES: usize = 12; #[allow(non_upper_case_globals)] -const crypto_aead_chacha20poly1305_ABYTES: usize = 16; +const crypto_aead_chacha20poly1305_ietf_ABYTES: usize = 16; #[allow(non_upper_case_globals)] const crypto_aead_aes256gcm_KEYBYTES: usize = 32; @@ -23,6 +23,8 @@ const crypto_aead_aes256gcm_NSECBYTES: usize = 0; 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; @@ -33,11 +35,12 @@ const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: usize = 524288; #[allow(non_upper_case_globals)] const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16777216; -struct Aes256State(*mut [u8; 512]); +struct Aes256State(*mut [u8; crypto_aead_aes256gcm_STATEBYTES]); impl Aes256State { fn new() -> Aes256State { - let ptr = aligned_alloc(512, 16) as *mut [u8; 512]; + let ptr = aligned_alloc(crypto_aead_aes256gcm_STATEBYTES, 16) + as *mut [u8; crypto_aead_aes256gcm_STATEBYTES]; Aes256State(ptr) } } @@ -63,28 +66,28 @@ extern { salt: *const [u8; crypto_pwhash_scryptsalsa208sha256_SALTBYTES], opslimit: c_ulonglong, memlimit: size_t) -> c_int; - pub fn crypto_aead_chacha20poly1305_encrypt( + 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_NSECBYTES], - npub: *const [u8; crypto_aead_chacha20poly1305_NPUBBYTES], - k: *const [u8; crypto_aead_chacha20poly1305_KEYBYTES]) -> c_int; - pub fn crypto_aead_chacha20poly1305_decrypt( + 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_NSECBYTES], + 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_NPUBBYTES], - k: *const [u8; crypto_aead_chacha20poly1305_KEYBYTES]) -> c_int; + 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; 512], + 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, @@ -95,7 +98,7 @@ extern { adlen: c_ulonglong, nsec: *const [u8; crypto_aead_aes256gcm_NSECBYTES], npub: *const [u8; crypto_aead_aes256gcm_NPUBBYTES], - state: *const [u8; 512]) -> c_int; + state: *const [u8; crypto_aead_aes256gcm_STATEBYTES]) -> c_int; pub fn crypto_aead_aes256gcm_decrypt_afternm( m: *mut u8, mlen: *mut c_ulonglong, @@ -105,7 +108,7 @@ extern { ad: *const u8, adlen: c_ulonglong, npub: *const [u8; crypto_aead_aes256gcm_NPUBBYTES], - state: *const [u8; 512]) -> c_int; + state: *const [u8; crypto_aead_aes256gcm_STATEBYTES]) -> c_int; } @@ -116,14 +119,13 @@ pub enum CryptoMethod { pub enum Crypto { None, - ChaCha20Poly1305{key: [u8; 32], nonce: [u8; 8]}, - AES256GCM{state: Aes256State, 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) + ChaCha20Poly1305{ + key: [u8; crypto_aead_chacha20poly1305_ietf_KEYBYTES], + nonce: [u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES] + }, + AES256GCM{ + state: Aes256State, + nonce: [u8; crypto_aead_aes256gcm_NPUBBYTES] } } @@ -175,7 +177,7 @@ impl Crypto { pub fn additional_bytes(&self) -> usize { match self { &Crypto::None => 0, - &Crypto::ChaCha20Poly1305{key: _, nonce: _} => crypto_aead_chacha20poly1305_ABYTES, + &Crypto::ChaCha20Poly1305{key: _, nonce: _} => crypto_aead_chacha20poly1305_ietf_ABYTES, &Crypto::AES256GCM{state: _, nonce: _} => crypto_aead_aes256gcm_ABYTES } } @@ -198,11 +200,11 @@ impl Crypto { } match method { CryptoMethod::ChaCha20 => { - let mut crypto_key = [0; crypto_aead_chacha20poly1305_KEYBYTES]; + let mut crypto_key = [0; crypto_aead_chacha20poly1305_ietf_KEYBYTES]; for i in 0..crypto_key.len() { crypto_key[i] = key[i]; } - let mut nonce = [0u8; crypto_aead_chacha20poly1305_NPUBBYTES]; + let mut nonce = [0u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) }; Crypto::ChaCha20Poly1305{key: crypto_key, nonce: nonce} }, @@ -228,7 +230,7 @@ impl Crypto { &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( + 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) @@ -236,8 +238,8 @@ impl Crypto { 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 + 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), @@ -254,7 +256,7 @@ impl Crypto { 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 + nonce.as_ptr() as *const [u8; crypto_aead_aes256gcm_NPUBBYTES], // Base pointer to public nonce state.0 // Base pointer to state ) }; match res { @@ -269,10 +271,11 @@ impl Crypto { match self { &mut Crypto::None => mlen, &mut Crypto::ChaCha20Poly1305{ref key, ref mut nonce} => { - inc_nonce_8(nonce); + inc_nonce_12(nonce); let mut clen: u64 = buf.len() as u64; - assert!(clen as usize >= mlen + crypto_aead_chacha20poly1305_ABYTES); - let res = unsafe { crypto_aead_chacha20poly1305_encrypt( + assert!(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 @@ -280,8 +283,8 @@ impl Crypto { 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 + 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); unsafe { @@ -292,6 +295,7 @@ impl Crypto { &mut Crypto::AES256GCM{ref state, ref mut nonce} => { inc_nonce_12(nonce); let mut clen: u64 = buf.len() as u64; + assert!(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 @@ -301,7 +305,7 @@ impl Crypto { 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 + 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); diff --git a/src/tests.rs b/src/tests.rs index 8b0bda8..619b08e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -31,7 +31,7 @@ fn udpmessage_encrypted() { let msg = Message::Data(&payload); let mut buf = [0; 1024]; let size = encode(&mut options, &msg, &mut buf[..], &mut crypto); - assert_eq!(size, 37); + assert_eq!(size, 41); assert_eq!(&buf[..8], &[118,112,110,1,1,0,0,0]); let (options2, msg2) = decode(&mut buf[..size], &mut crypto).unwrap(); assert_eq!(options, options2); @@ -261,13 +261,13 @@ fn encrypt_decrypt_chacha20poly1305() { for i in 0..msg_bytes.len() { buffer[i] = msg_bytes[i]; } - let mut nonce1 = [0u8; 8]; + let mut nonce1 = [0u8; 12]; 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 mut nonce2 = [0u8; 12]; let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce2, &header); assert!(nonce1 != nonce2); receiver.decrypt(&mut buffer[..size], &nonce2, &header).unwrap(); @@ -276,6 +276,10 @@ fn encrypt_decrypt_chacha20poly1305() { #[test] fn encrypt_decrypt_aes256() { + Crypto::init(); + if ! Crypto::aes256_available() { + return + } let mut sender = Crypto::from_shared_key(CryptoMethod::AES256, "test"); let receiver = Crypto::from_shared_key(CryptoMethod::AES256, "test"); let msg = "HelloWorld0123456789"; @@ -285,13 +289,13 @@ fn encrypt_decrypt_aes256() { for i in 0..msg_bytes.len() { buffer[i] = msg_bytes[i]; } - let mut nonce1 = [0u8; 8]; + let mut nonce1 = [0u8; 12]; 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 mut nonce2 = [0u8; 12]; let size = sender.encrypt(&mut buffer, msg_bytes.len(), &mut nonce2, &header); assert!(nonce1 != nonce2); receiver.decrypt(&mut buffer[..size], &nonce2, &header).unwrap(); diff --git a/vpncloud.md b/vpncloud.md index 5403b07..a0260d5 100644 --- a/vpncloud.md +++ b/vpncloud.md @@ -235,12 +235,12 @@ Every packet sent over UDP contains the following header (in order): - Method `0`, **No encryption**: Rest of the data can be read without decrypting it. - - Method `1`, **ChaCha20Poly1305**: The header is followed by a 8 byte + - Method `1`, **ChaCha20**: The header is followed by a 12 byte *nonce*. The rest of the data is encrypted with the - `libsodium::crypto_aead_chacha20poly1305` method, using the 8 byte header - as additional data. + `libsodium::crypto_aead_chacha20poly1305_ietf` method, using the 8 byte + header as additional data. - - Method `2`, **AES256GCM**: The header is followed by a 12 byte *nonce*. + - Method `2`, **AES256**: 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.