Send encrypted DNS responses

pull/5/head
Frank Denis 5 years ago
parent 65c2bba989
commit eb1b857274

@ -182,6 +182,24 @@ impl SharedKey {
decrypted.truncate(idx); decrypted.truncate(idx);
Ok(decrypted) Ok(decrypted)
} }
pub fn encrypt(&self, nonce: &[u8], mut plaintext: Vec<u8>) -> Result<Vec<u8>, 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 { pub fn bin2hex(bin: &[u8]) -> String {

@ -12,18 +12,13 @@ pub const DNSCRYPT_CLIENT_MAGIC_SIZE: usize = 8;
pub const DNSCRYPT_CLIENT_PK_SIZE: usize = 32; pub const DNSCRYPT_CLIENT_PK_SIZE: usize = 32;
pub const DNSCRYPT_CLIENT_NONCE_SIZE: usize = pub const DNSCRYPT_CLIENT_NONCE_SIZE: usize =
crypto_box_curve25519xchacha20poly1305_HALFNONCEBYTES as usize; crypto_box_curve25519xchacha20poly1305_HALFNONCEBYTES as usize;
pub const DNSCRYPT_FULL_NONCE_SIZE: usize =
crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize;
pub fn decrypt( pub fn decrypt(
wrapped_packet: &[u8], wrapped_packet: &[u8],
dnscrypt_encryption_params_set: &[DNSCryptEncryptionParams], dnscrypt_encryption_params_set: &[DNSCryptEncryptionParams],
) -> Result< ) -> Result<(SharedKey, [u8; DNSCRYPT_FULL_NONCE_SIZE as usize], Vec<u8>), Error> {
(
SharedKey,
[u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize],
Vec<u8>,
),
Error,
> {
ensure!( ensure!(
wrapped_packet.len() wrapped_packet.len()
>= DNSCRYPT_CLIENT_MAGIC_SIZE >= DNSCRYPT_CLIENT_MAGIC_SIZE
@ -46,7 +41,7 @@ pub fn decrypt(
.find(|p| p.client_magic() == client_magic) .find(|p| p.client_magic() == client_magic)
.ok_or_else(|| format_err!("Client magic not found"))?; .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); &mut nonce[..DNSCRYPT_CLIENT_NONCE_SIZE].copy_from_slice(client_nonce);
let resolver_kp = dnscrypt_encryption_params.resolver_kp(); let resolver_kp = dnscrypt_encryption_params.resolver_kp();
let shared_key = resolver_kp.compute_shared_key(client_pk)?; let shared_key = resolver_kp.compute_shared_key(client_pk)?;
@ -57,9 +52,13 @@ pub fn decrypt(
} }
pub fn encrypt( pub fn encrypt(
packet: &[u8], packet: Vec<u8>,
shared_key: &SharedKey, shared_key: &SharedKey,
nonce: &[u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize], nonce: &[u8; DNSCRYPT_FULL_NONCE_SIZE as usize],
) { ) -> Result<Vec<u8>, 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)
} }

@ -76,8 +76,13 @@ async fn respond_to_query(
client_ctx: ClientCtx, client_ctx: ClientCtx,
packet: Vec<u8>, packet: Vec<u8>,
shared_key: Option<SharedKey>, shared_key: Option<SharedKey>,
nonce: Option<[u8; DNSCRYPT_FULL_NONCE_SIZE]>,
) -> Result<(), Error> { ) -> Result<(), Error> {
ensure!(dns::is_response(&packet), "Packet is not a response"); 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 { match client_ctx {
ClientCtx::Udp(client_ctx) => { ClientCtx::Udp(client_ctx) => {
let net_udp_socket = client_ctx.net_udp_socket; let net_udp_socket = client_ctx.net_udp_socket;
@ -112,7 +117,7 @@ async fn handle_client_query(
&globals.provider_name, &globals.provider_name,
&globals.dnscrypt_encryption_params_set, &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"); bail!("Unencrypted query");
} }
@ -175,7 +180,7 @@ async fn handle_client_query(
); );
} }
dns::set_tid(&mut response, original_tid); 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<Globals>, tcp_listener: TcpListener) -> Result<(), Error> { async fn tcp_acceptor(globals: Arc<Globals>, tcp_listener: TcpListener) -> Result<(), Error> {

Loading…
Cancel
Save