1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use bytes::BytesMut;
use chacha20poly1305::{
    aead::{AeadInPlace, NewAead},
    ChaCha8Poly1305, Key, Nonce, Tag,
};
use quinn_proto::crypto::{CryptoError, HeaderKey, KeyPair, PacketKey};

pub const HEADER_KEYPAIR: KeyPair<PlaintextHeaderKey> = KeyPair {
    local: PlaintextHeaderKey,
    remote: PlaintextHeaderKey,
};

#[derive(Clone)]
pub struct ChaCha8PacketKey(ChaCha8Poly1305);

impl ChaCha8PacketKey {
    pub fn new(key: [u8; 32]) -> Self {
        let key = Key::from(key);
        Self(ChaCha8Poly1305::new(&key))
    }
}

impl PacketKey for ChaCha8PacketKey {
    fn encrypt(&self, packet: u64, buf: &mut [u8], header_len: usize) {
        let mut nonce = [0; 12];
        nonce[4..].copy_from_slice(&packet.to_le_bytes());
        let nonce = Nonce::from(nonce);
        let (header, payload) = buf.split_at_mut(header_len);
        let (content, auth) = payload.split_at_mut(payload.len() - self.tag_len());
        let tag = self
            .0
            .encrypt_in_place_detached(&nonce, header, content)
            .unwrap();
        auth.copy_from_slice(&tag);
    }

    fn decrypt(
        &self,
        packet: u64,
        header: &[u8],
        payload: &mut BytesMut,
    ) -> Result<(), CryptoError> {
        let mut nonce = [0; 12];
        nonce[4..].copy_from_slice(&packet.to_le_bytes());
        let nonce = Nonce::from(nonce);
        let len = payload.len() - self.tag_len();
        let (content, tag) = payload.split_at_mut(len);
        let tag = Tag::from_slice(tag);
        self.0
            .decrypt_in_place_detached(&nonce, header, content, tag)
            .map_err(|_| CryptoError)?;
        payload.truncate(len);
        Ok(())
    }

    fn tag_len(&self) -> usize {
        16
    }

    fn confidentiality_limit(&self) -> u64 {
        u64::MAX
    }

    fn integrity_limit(&self) -> u64 {
        u64::MAX
    }
}

pub struct PlaintextHeaderKey;

impl HeaderKey for PlaintextHeaderKey {
    fn decrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {}

    fn encrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {}

    fn sample_size(&self) -> usize {
        0
    }
}