(
packet: Vec<u8>,
params: &EncryptionParams,
max_packet_size: usize,
)
| 239 | } |
| 240 | |
| 241 | pub fn encrypt( |
| 242 | packet: Vec<u8>, |
| 243 | params: &EncryptionParams, |
| 244 | max_packet_size: usize, |
| 245 | ) -> Result<Vec<u8>, Error> { |
| 246 | // Every response is framed the same way: the response magic followed by the |
| 247 | // full nonce. Only the encryption of the payload differs between schemes. |
| 248 | let nonce = match params { |
| 249 | EncryptionParams::Classical { nonce, .. } | EncryptionParams::Pq { nonce, .. } => nonce, |
| 250 | }; |
| 251 | let mut wrapped_packet = Vec::with_capacity(DNS_MAX_PACKET_SIZE); |
| 252 | wrapped_packet.extend_from_slice(&DNSCRYPT_RESPONSE_MAGIC); |
| 253 | wrapped_packet.extend_from_slice(nonce); |
| 254 | match params { |
| 255 | EncryptionParams::Classical { shared_key, nonce } => { |
| 256 | ensure!( |
| 257 | max_packet_size >= wrapped_packet.len(), |
| 258 | "Max packet size too short" |
| 259 | ); |
| 260 | let max_encrypted_size = max_packet_size - wrapped_packet.len(); |
| 261 | shared_key.encrypt_into( |
| 262 | &mut wrapped_packet, |
| 263 | nonce, |
| 264 | &nonce[..DNSCRYPT_QUERY_NONCE_SIZE], |
| 265 | packet, |
| 266 | max_encrypted_size, |
| 267 | )?; |
| 268 | } |
| 269 | EncryptionParams::Pq { |
| 270 | shared_key, |
| 271 | nonce, |
| 272 | control, |
| 273 | } => { |
| 274 | ensure!( |
| 275 | max_packet_size >= wrapped_packet.len() + DNSCRYPT_MAC_SIZE, |
| 276 | "Max packet size too short" |
| 277 | ); |
| 278 | let max_plaintext = max_packet_size - wrapped_packet.len() - DNSCRYPT_MAC_SIZE; |
| 279 | let mut plaintext = Vec::with_capacity(2 + control.len() + packet.len() + 64); |
| 280 | plaintext.extend_from_slice(&(control.len() as u16).to_be_bytes()); |
| 281 | plaintext.extend_from_slice(control); |
| 282 | plaintext.extend_from_slice(&packet); |
| 283 | pq::pad7816(&mut plaintext, 64); |
| 284 | ensure!(plaintext.len() <= max_plaintext, "PQ response too large to pad"); |
| 285 | let encrypted = shared_key.seal_raw(nonce, &plaintext); |
| 286 | wrapped_packet.extend_from_slice(&encrypted); |
| 287 | } |
| 288 | } |
| 289 | Ok(wrapped_packet) |
| 290 | } |
| 291 | |
| 292 | pub fn may_be_quic(packet: &[u8]) -> bool { |
| 293 | !packet.is_empty() && ((80..=127).contains(&packet[0]) || (192..=255).contains(&packet[0])) |
no test coverage detected