From eb1b8572747ba2069d596ff9354cadb9f9b5f9ba Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 18 Sep 2019 01:44:47 +0200 Subject: [PATCH] Send encrypted DNS responses --- src/crypto.rs | 18 ++++++++++++++++++ src/dnscrypt.rs | 25 ++++++++++++------------- src/main.rs | 9 +++++++-- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/crypto.rs b/src/crypto.rs index ef25844..54039a9 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -182,6 +182,24 @@ impl SharedKey { decrypted.truncate(idx); Ok(decrypted) } + + pub fn encrypt(&self, nonce: &[u8], mut plaintext: Vec) -> Result, Error> { + plaintext.push(0x80); + let plaintext_len = plaintext.len(); + let mut encrypted = + vec![0u8; plaintext_len + crypto_box_curve25519xchacha20poly1305_MACBYTES as usize]; + let res = unsafe { + libsodium_sys::crypto_box_curve25519xchacha20poly1305_easy_afternm( + encrypted.as_mut_ptr(), + plaintext.as_ptr(), + plaintext_len as _, + nonce.as_ptr(), + self.0.as_ptr(), + ) + }; + ensure!(res == 0, "Unable to encrypt"); + Ok(encrypted) + } } pub fn bin2hex(bin: &[u8]) -> String { diff --git a/src/dnscrypt.rs b/src/dnscrypt.rs index 097d09c..568fecf 100644 --- a/src/dnscrypt.rs +++ b/src/dnscrypt.rs @@ -12,18 +12,13 @@ pub const DNSCRYPT_CLIENT_MAGIC_SIZE: usize = 8; pub const DNSCRYPT_CLIENT_PK_SIZE: usize = 32; pub const DNSCRYPT_CLIENT_NONCE_SIZE: usize = crypto_box_curve25519xchacha20poly1305_HALFNONCEBYTES as usize; +pub const DNSCRYPT_FULL_NONCE_SIZE: usize = + crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize; pub fn decrypt( wrapped_packet: &[u8], dnscrypt_encryption_params_set: &[DNSCryptEncryptionParams], -) -> Result< - ( - SharedKey, - [u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize], - Vec, - ), - Error, -> { +) -> Result<(SharedKey, [u8; DNSCRYPT_FULL_NONCE_SIZE as usize], Vec), Error> { ensure!( wrapped_packet.len() >= DNSCRYPT_CLIENT_MAGIC_SIZE @@ -46,7 +41,7 @@ pub fn decrypt( .find(|p| p.client_magic() == client_magic) .ok_or_else(|| format_err!("Client magic not found"))?; - let mut nonce = [0u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize]; + let mut nonce = [0u8; DNSCRYPT_FULL_NONCE_SIZE as usize]; &mut nonce[..DNSCRYPT_CLIENT_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)?; @@ -57,9 +52,13 @@ pub fn decrypt( } pub fn encrypt( - packet: &[u8], + packet: Vec, shared_key: &SharedKey, - nonce: &[u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize], -) { - // + nonce: &[u8; DNSCRYPT_FULL_NONCE_SIZE as usize], +) -> Result, Error> { + let mut wrapped_packet = vec![0x72u8, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38]; + wrapped_packet.extend_from_slice(nonce); + let encrypted_packet = shared_key.encrypt(nonce, packet)?; + wrapped_packet.extend_from_slice(&encrypted_packet); + Ok(wrapped_packet) } diff --git a/src/main.rs b/src/main.rs index 386b599..2702670 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,8 +76,13 @@ async fn respond_to_query( client_ctx: ClientCtx, packet: Vec, shared_key: Option, + nonce: Option<[u8; DNSCRYPT_FULL_NONCE_SIZE]>, ) -> Result<(), Error> { ensure!(dns::is_response(&packet), "Packet is not a response"); + let packet = match &shared_key { + None => packet, + Some(shared_key) => dnscrypt::encrypt(packet, shared_key, nonce.as_ref().unwrap())?, + }; match client_ctx { ClientCtx::Udp(client_ctx) => { let net_udp_socket = client_ctx.net_udp_socket; @@ -112,7 +117,7 @@ async fn handle_client_query( &globals.provider_name, &globals.dnscrypt_encryption_params_set, )? { - return respond_to_query(client_ctx, synth_packet, None).await; + return respond_to_query(client_ctx, synth_packet, None, None).await; } bail!("Unencrypted query"); } @@ -175,7 +180,7 @@ async fn handle_client_query( ); } dns::set_tid(&mut response, original_tid); - respond_to_query(client_ctx, response, Some(shared_key)).await + respond_to_query(client_ctx, response, Some(shared_key), Some(nonce)).await } async fn tcp_acceptor(globals: Arc, tcp_listener: TcpListener) -> Result<(), Error> {