mirror of https://github.com/dswd/vpncloud.git
Using ietf chacha20 version and fixed crypto tests
This commit is contained in:
parent
c2f627bc07
commit
d8276fad58
|
@ -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);
|
||||
|
|
14
src/tests.rs
14
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();
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue