MCPcopy Create free account
hub / github.com/DNSCrypt/encrypted-dns-server / decrypt_pq_resumed

Function decrypt_pq_resumed

src/dnscrypt.rs:195–239  ·  view source on GitHub ↗

Decrypt a resumed PQ query, validating its ticket and deriving the per-query key without a KEM decapsulation.

(
    wrapped_packet: &[u8],
    dnscrypt_encryption_params_set: &[Arc<DNSCryptEncryptionParams>],
    pq_ticket_key: &pq::TicketKey,
)

Source from the content-addressed store, hash-verified

193/// Decrypt a resumed PQ query, validating its ticket and deriving the
194/// per-query key without a KEM decapsulation.
195fn decrypt_pq_resumed(
196 wrapped_packet: &[u8],
197 dnscrypt_encryption_params_set: &[Arc<DNSCryptEncryptionParams>],
198 pq_ticket_key: &pq::TicketKey,
199) -> Result<(EncryptionParams, Vec<u8>), Error> {
200 let magic = pq::PQ_RESUME_MAGIC.len();
201 let nonce_size = DNSCRYPT_QUERY_NONCE_SIZE;
202 ensure!(wrapped_packet.len() >= magic + 2, "Short resumed query");
203 let ticket_len =
204 u16::from_be_bytes([wrapped_packet[magic], wrapped_packet[magic + 1]]) as usize;
205 let ticket_off = magic + 2;
206 ensure!(
207 wrapped_packet.len() >= ticket_off + ticket_len + nonce_size + DNSCRYPT_MAC_SIZE + DNS_HEADER_SIZE,
208 "Short resumed query"
209 );
210 let ticket = &wrapped_packet[ticket_off..ticket_off + ticket_len];
211 let client_nonce = &wrapped_packet[ticket_off + ticket_len..ticket_off + ticket_len + nonce_size];
212 let encrypted_packet = &wrapped_packet[ticket_off + ticket_len + nonce_size..];
213
214 let opened = pq::open_ticket(pq_ticket_key, ticket)?;
215 let fields = pq::parse_ticket_plain(&opened)?;
216 ensure!(fields.ticket_expiry > now(), "Expired ticket");
217 ensure!(
218 dnscrypt_encryption_params_set.iter().any(|p| p.pq().is_some_and(|pq| {
219 pq.client_magic() == fields.client_magic && pq.es_version() == fields.es_version
220 })),
221 "Ticket does not match a current certificate"
222 );
223
224 let resumed_key =
225 pq::resumed_shared_key(&fields.resume_secret, &fields.client_magic, client_nonce, ticket);
226 let mut nonce = [0u8; DNSCRYPT_FULL_NONCE_SIZE];
227 nonce[..nonce_size].copy_from_slice(client_nonce);
228 let packet = resumed_key.decrypt(&nonce, encrypted_packet)?;
229 debug!("PQ resumed query accepted (no decapsulation)");
230 rand::rng().fill_bytes(&mut nonce[nonce_size..]);
231 Ok((
232 EncryptionParams::Pq {
233 shared_key: resumed_key,
234 nonce,
235 control: Vec::new(),
236 },
237 packet,
238 ))
239}
240
241pub fn encrypt(
242 packet: Vec<u8>,

Callers 1

decryptFunction · 0.85

Calls 5

open_ticketFunction · 0.85
parse_ticket_plainFunction · 0.85
resumed_shared_keyFunction · 0.85
newFunction · 0.85
decryptMethod · 0.80

Tested by

no test coverage detected