1use bytes::BytesMut;
2use chacha20poly1305::{
3 aead::{AeadInPlace, NewAead},
4 ChaCha8Poly1305, Key, Nonce, Tag,
5};
6use quinn_proto::crypto::{CryptoError, HeaderKey, KeyPair, PacketKey};
7
8pub fn header_keypair() -> KeyPair<Box<dyn HeaderKey>> {
9 KeyPair {
10 local: Box::new(PlaintextHeaderKey),
11 remote: Box::new(PlaintextHeaderKey),
12 }
13}
14
15#[derive(Clone)]
16pub struct ChaCha8PacketKey(ChaCha8Poly1305);
17
18impl ChaCha8PacketKey {
19 pub fn new(key: [u8; 32]) -> Self {
20 let key = Key::from(key);
21 Self(ChaCha8Poly1305::new(&key))
22 }
23}
24
25impl PacketKey for ChaCha8PacketKey {
26 fn encrypt(&self, packet: u64, buf: &mut [u8], header_len: usize) {
27 let mut nonce = [0; 12];
28 nonce[4..].copy_from_slice(&packet.to_le_bytes());
29 let nonce = Nonce::from(nonce);
30 let (header, payload) = buf.split_at_mut(header_len);
31 let (content, auth) = payload.split_at_mut(payload.len() - self.tag_len());
32 let tag = self
33 .0
34 .encrypt_in_place_detached(&nonce, header, content)
35 .unwrap();
36 auth.copy_from_slice(&tag);
37 }
38
39 fn decrypt(
40 &self,
41 packet: u64,
42 header: &[u8],
43 payload: &mut BytesMut,
44 ) -> Result<(), CryptoError> {
45 let mut nonce = [0; 12];
46 nonce[4..].copy_from_slice(&packet.to_le_bytes());
47 let nonce = Nonce::from(nonce);
48 let len = payload.len() - self.tag_len();
49 let (content, tag) = payload.split_at_mut(len);
50 let tag = Tag::from_slice(tag);
51 self.0
52 .decrypt_in_place_detached(&nonce, header, content, tag)
53 .map_err(|_| CryptoError)?;
54 payload.truncate(len);
55 Ok(())
56 }
57
58 fn tag_len(&self) -> usize {
59 16
60 }
61
62 fn confidentiality_limit(&self) -> u64 {
63 u64::MAX
64 }
65
66 fn integrity_limit(&self) -> u64 {
67 u64::MAX
68 }
69}
70
71pub struct PlaintextHeaderKey;
72
73impl HeaderKey for PlaintextHeaderKey {
74 fn decrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {}
75
76 fn encrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {}
77
78 fn sample_size(&self) -> usize {
79 0
80 }
81}