pull/5/head
Frank Denis 5 years ago
parent 0505f886e5
commit 67a935f291

@ -19,6 +19,7 @@ log = "0.4.8"
net2 = "0.2.33"
parking_lot = "0.9.0"
rand = "0.7.2"
siphasher = "0.3.0"
tokio = "=0.2.0-alpha.4"
tokio-net = "=0.2.0-alpha.4"

@ -1,7 +1,9 @@
use crate::errors::*;
use libsodium_sys::*;
use siphasher::sip::SipHasher13;
use std::ffi::CStr;
use std::hash::Hasher;
use std::ptr;
#[allow(non_upper_case_globals)]
@ -187,14 +189,39 @@ impl SharedKey {
&self,
target: &mut Vec<u8>,
nonce: &[u8],
mut plaintext: Vec<u8>,
client_nonce: &[u8],
plaintext: Vec<u8>,
max_target_size: usize,
) -> Result<(), Error> {
plaintext.push(0x80);
ensure!(
max_target_size >= crypto_box_curve25519xchacha20poly1305_MACBYTES as usize,
"Max target size too small"
);
let plaintext_len = plaintext.len();
let max_padded_plaintext_len =
max_target_size - crypto_box_curve25519xchacha20poly1305_MACBYTES as usize;
let mut hasher = SipHasher13::new();
hasher.write(&self.0);
hasher.write(&client_nonce);
let pad_size: usize = 1 + (hasher.finish() as usize & 0xff);
let mut padded_plaintext_len = (plaintext_len + pad_size) & !63;
if padded_plaintext_len < plaintext_len {
padded_plaintext_len += 64;
}
if padded_plaintext_len > max_padded_plaintext_len {
padded_plaintext_len = max_padded_plaintext_len;
}
ensure!(padded_plaintext_len > plaintext_len, "No room for padding");
let mut padded_plaintext = plaintext;
padded_plaintext.push(0x80);
while padded_plaintext.len() != padded_plaintext_len {
padded_plaintext.push(0x00);
}
let padded_plaintext_len = padded_plaintext.len();
let target_header_len = target.len();
target.resize(
target_header_len
+ plaintext_len
+ padded_plaintext_len
+ crypto_box_curve25519xchacha20poly1305_MACBYTES as usize,
0,
);
@ -202,8 +229,8 @@ impl SharedKey {
let res = unsafe {
libsodium_sys::crypto_box_curve25519xchacha20poly1305_easy_afternm(
encrypted.as_mut_ptr(),
plaintext.as_ptr(),
plaintext_len as _,
padded_plaintext.as_ptr(),
padded_plaintext_len as _,
nonce.as_ptr(),
self.0.as_ptr(),
)

@ -66,7 +66,7 @@ pub fn decrypt(
.ok_or_else(|| format_err!("Client magic not found"))?;
let mut nonce = [0u8; DNSCRYPT_FULL_NONCE_SIZE as usize];
&mut nonce[..DNSCRYPT_QUERY_NONCE_SIZE].copy_from_slice(client_nonce);
nonce[..DNSCRYPT_QUERY_NONCE_SIZE].copy_from_slice(client_nonce);
let resolver_kp = dnscrypt_encryption_params.resolver_kp();
let shared_key = resolver_kp.compute_shared_key(client_pk)?;
let packet = shared_key.decrypt(&nonce, encrypted_packet)?;
@ -79,10 +79,22 @@ pub fn encrypt(
packet: Vec<u8>,
shared_key: &SharedKey,
nonce: &[u8; DNSCRYPT_FULL_NONCE_SIZE as usize],
max_packet_size: usize,
) -> Result<Vec<u8>, Error> {
let mut wrapped_packet = Vec::with_capacity(DNS_MAX_PACKET_SIZE);
wrapped_packet.extend_from_slice(&[0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38]);
wrapped_packet.extend_from_slice(nonce);
shared_key.encrypt_into(&mut wrapped_packet, nonce, packet)?;
ensure!(
max_packet_size >= wrapped_packet.len(),
"Max packet size too short"
);
let max_encrypted_size = max_packet_size - wrapped_packet.len();
shared_key.encrypt_into(
&mut wrapped_packet,
nonce,
&nonce[..DNSCRYPT_QUERY_NONCE_SIZE],
packet,
max_encrypted_size,
)?;
Ok(wrapped_packet)
}

@ -73,12 +73,11 @@ fn maybe_truncate_response(
client_ctx: &ClientCtx,
packet: Vec<u8>,
response: Vec<u8>,
original_packet_len: usize,
original_packet_size: usize,
) -> Result<Vec<u8>, Error> {
if let ClientCtx::Udp(_) = client_ctx {
let encrypted_response_min_len =
response.len() + DNSCRYPT_RESPONSE_HEADER_SIZE + DNSCRYPT_RESPONSE_MIN_PADDING_SIZE;
if encrypted_response_min_len > original_packet_len
let encrypted_response_min_len = response.len() + DNSCRYPT_RESPONSE_MIN_OVERHEAD;
if encrypted_response_min_len > original_packet_size
|| encrypted_response_min_len > DNSCRYPT_UDP_RESPONSE_MAX_SIZE
{
return Ok(dns::serve_truncated(packet)?);
@ -91,17 +90,22 @@ async fn respond_to_query(
client_ctx: ClientCtx,
packet: Vec<u8>,
response: Vec<u8>,
original_packet_len: usize,
original_packet_size: usize,
shared_key: Option<SharedKey>,
nonce: Option<[u8; DNSCRYPT_FULL_NONCE_SIZE]>,
) -> Result<(), Error> {
ensure!(dns::is_response(&response), "Packet is not a response");
let max_response_size = match client_ctx {
ClientCtx::Udp(_) => original_packet_size,
ClientCtx::Tcp(_) => DNSCRYPT_TCP_RESPONSE_MAX_SIZE,
};
let response = match &shared_key {
None => response,
Some(shared_key) => dnscrypt::encrypt(
maybe_truncate_response(&client_ctx, packet, response, original_packet_len)?,
maybe_truncate_response(&client_ctx, packet, response, original_packet_size)?,
shared_key,
nonce.as_ref().unwrap(),
max_response_size,
)?,
};
match client_ctx {
@ -131,7 +135,7 @@ async fn handle_client_query(
client_ctx: ClientCtx,
encrypted_packet: Vec<u8>,
) -> Result<(), Error> {
let original_packet_len = encrypted_packet.len();
let original_packet_size = encrypted_packet.len();
let (shared_key, nonce, mut packet) =
match dnscrypt::decrypt(&encrypted_packet, &globals.dnscrypt_encryption_params_set) {
Ok(x) => x,
@ -146,7 +150,7 @@ async fn handle_client_query(
client_ctx,
packet,
synth_packet,
original_packet_len,
original_packet_size,
None,
None,
)
@ -217,7 +221,7 @@ async fn handle_client_query(
client_ctx,
packet,
response,
original_packet_len,
original_packet_size,
Some(shared_key),
Some(nonce),
)

Loading…
Cancel
Save