Refactor a bit, remove question padding

pull/5/head
Frank Denis 5 years ago
parent 5f0bb6daf5
commit 337eb4924d

@ -142,29 +142,45 @@ impl CryptKeyPair {
kp
}
pub fn decrypt(
&self,
client_pk: &[u8],
nonce: &[u8],
encrypted: &[u8],
) -> Result<Vec<u8>, Error> {
pub fn compute_shared_key(&self, pk: &[u8]) -> Result<SharedKey, Error> {
let mut shared_key = SharedKey::default();
let res = unsafe {
crypto_box_curve25519xchacha20poly1305_beforenm(
shared_key.0.as_mut_ptr(),
pk.as_ptr(),
self.sk.0.as_ptr(),
)
};
ensure!(res == 0, "Weak public key");
Ok(shared_key)
}
}
#[derive(Debug, Default)]
pub struct SharedKey([u8; crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES as usize]);
impl SharedKey {
pub fn decrypt(&self, nonce: &[u8], encrypted: &[u8]) -> Result<Vec<u8>, Error> {
let encrypted_len = encrypted.len();
let mut decrypted =
vec![0u8; encrypted_len - crypto_box_curve25519xchacha20poly1305_MACBYTES as usize];
let res = unsafe {
libsodium_sys::crypto_box_curve25519xchacha20poly1305_open_easy(
libsodium_sys::crypto_box_curve25519xchacha20poly1305_open_easy_afternm(
decrypted.as_mut_ptr(),
encrypted.as_ptr(),
encrypted_len as _,
nonce.as_ptr(),
client_pk.as_ptr(),
self.sk.as_bytes().as_ptr(),
self.0.as_ptr(),
)
};
match res {
0 => Ok(decrypted),
_ => bail!("Unable to decrypt"),
}
ensure!(res == 0, "Unable to decrypt");
let idx = decrypted
.iter()
.rposition(|x| *x != 0x00)
.ok_or_else(|| format_err!("Padding error"))?;
ensure!(decrypted[idx] == 0x80, "Padding error");
decrypted.truncate(idx);
Ok(decrypted)
}
}

@ -295,6 +295,12 @@ pub fn serve_certificates<'t>(
expected_qname: &str,
dnscrypt_encryption_params_set: impl IntoIterator<Item = &'t DNSCryptEncryptionParams>,
) -> Result<Option<Vec<u8>>, Error> {
ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
ensure!(qdcount(&client_packet) == 1, "No question");
ensure!(
!is_response(&client_packet),
"Question expected, but got a response instead"
);
let offset = skip_name(client_packet, DNS_HEADER_SIZE)?;
ensure!(client_packet.len() - offset >= 4, "Short packet");
let qtype = BigEndian::read_u16(&client_packet[offset..]);

@ -11,61 +11,37 @@ pub const DNSCRYPT_CLIENT_MAGIC_SIZE: usize = 8;
pub const DNSCRYPT_CLIENT_PK_SIZE: usize = 32;
pub const DNSCRYPT_CLIENT_NONCE_SIZE: usize = 12;
pub struct DNSCryptQuery<'t> {
wrapped_packet: &'t [u8],
}
impl<'t> DNSCryptQuery<'t> {
pub fn new(
wrapped_packet: &'t [u8],
dnscrypt_encryption_params_set: &[DNSCryptEncryptionParams],
) -> Result<Self, Error> {
ensure!(
wrapped_packet.len()
>= DNSCRYPT_CLIENT_MAGIC_SIZE
+ DNSCRYPT_CLIENT_PK_SIZE
+ DNSCRYPT_CLIENT_NONCE_SIZE
+ DNS_HEADER_SIZE,
"Short packet"
);
let dnscrypt_query = DNSCryptQuery { wrapped_packet };
let client_magic = dnscrypt_query.client_magic();
let dnscrypt_encryption_params = dnscrypt_encryption_params_set
.iter()
.find(|p| p.client_magic() == client_magic)
.ok_or_else(|| format_err!("Client magic not found"))?;
let encrypted_packet = dnscrypt_query.encrypted_packet();
let encrypted_packet_len = encrypted_packet.len();
let mut nonce = vec![0u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize];
&mut nonce[..crypto_box_curve25519xchacha20poly1305_HALFNONCEBYTES]
.copy_from_slice(dnscrypt_query.client_nonce());
let resolver_kp = dnscrypt_encryption_params.resolver_kp();
resolver_kp.decrypt(dnscrypt_query.client_pk(), &nonce, encrypted_packet)?;
dbg!("ok");
Ok(dnscrypt_query)
}
pub fn client_magic(&self) -> &[u8] {
&self.wrapped_packet[..DNSCRYPT_CLIENT_MAGIC_SIZE]
}
pub fn client_pk(&self) -> &[u8] {
&self.wrapped_packet
[DNSCRYPT_CLIENT_MAGIC_SIZE..DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE]
}
pub fn client_nonce(&self) -> &[u8] {
&self.wrapped_packet[DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE
..DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE + DNSCRYPT_CLIENT_NONCE_SIZE]
}
pub fn encrypted_packet(&self) -> &[u8] {
&self.wrapped_packet
[DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE + DNSCRYPT_CLIENT_NONCE_SIZE..]
}
pub fn into_packet(self) -> Vec<u8> {
self.encrypted_packet().to_vec()
}
pub fn decrypt(
wrapped_packet: &[u8],
dnscrypt_encryption_params_set: &[DNSCryptEncryptionParams],
) -> Result<Vec<u8>, Error> {
ensure!(
wrapped_packet.len()
>= DNSCRYPT_CLIENT_MAGIC_SIZE
+ DNSCRYPT_CLIENT_PK_SIZE
+ DNSCRYPT_CLIENT_NONCE_SIZE
+ DNS_HEADER_SIZE,
"Short packet"
);
let client_magic = &wrapped_packet[..DNSCRYPT_CLIENT_MAGIC_SIZE];
let client_pk = &wrapped_packet
[DNSCRYPT_CLIENT_MAGIC_SIZE..DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE];
let client_nonce = &wrapped_packet[DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE
..DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE + DNSCRYPT_CLIENT_NONCE_SIZE];
let encrypted_packet = &wrapped_packet
[DNSCRYPT_CLIENT_MAGIC_SIZE + DNSCRYPT_CLIENT_PK_SIZE + DNSCRYPT_CLIENT_NONCE_SIZE..];
let encrypted_packet_len = encrypted_packet.len();
let dnscrypt_encryption_params = dnscrypt_encryption_params_set
.iter()
.find(|p| p.client_magic() == client_magic)
.ok_or_else(|| format_err!("Client magic not found"))?;
let mut nonce = vec![0u8; crypto_box_curve25519xchacha20poly1305_NONCEBYTES as usize];
&mut nonce[..crypto_box_curve25519xchacha20poly1305_HALFNONCEBYTES]
.copy_from_slice(client_nonce);
let resolver_kp = dnscrypt_encryption_params.resolver_kp();
let shared_secret = resolver_kp.compute_shared_key(client_pk)?;
let packet = shared_secret.decrypt(&nonce, encrypted_packet)?;
Ok(packet)
}

@ -98,16 +98,11 @@ async fn handle_client_query(
client_ctx: ClientCtx,
encrypted_packet: Vec<u8>,
) -> Result<(), Error> {
let packet = DNSCryptQuery::new(&encrypted_packet, &globals.dnscrypt_encryption_params_set);
let packet = dnscrypt::decrypt(&encrypted_packet, &globals.dnscrypt_encryption_params_set);
let mut packet = match packet {
Ok(packet) => packet,
Err(_) => {
let packet = encrypted_packet;
ensure!(packet.len() >= DNS_HEADER_SIZE, "Short packet");
ensure!(dns::qdcount(&packet) == 1, "No question");
ensure!(
!dns::is_response(&packet),
"Question expected, but got a response instead"
);
if let Some(synth_packet) = serve_certificates(
&packet,
&globals.provider_name,
@ -117,8 +112,13 @@ async fn handle_client_query(
}
bail!("Unencrypted query");
}
Ok(packet) => packet.into_packet(),
};
ensure!(packet.len() >= DNS_HEADER_SIZE, "Short packet");
ensure!(qdcount(&packet) == 1, "No question");
ensure!(
!dns::is_response(&packet),
"Question expected, but got a response instead"
);
let original_tid = dns::tid(&packet);
let tid = random();

Loading…
Cancel
Save