ssh/algorithm/encryption/
chacha20_poly1305_openssh.rs

1use crate::algorithm::hash::Hash;
2use crate::algorithm::mac::Mac;
3use crate::error::SshError;
4use crate::{algorithm::encryption::Encryption, error::SshResult};
5use ring::aead::chacha20_poly1305_openssh::{OpeningKey, SealingKey};
6
7const KEY_SIZE: usize = 64;
8const IV_SIZE: usize = 0;
9const BLOCK_SIZE: usize = 0;
10const MAC_SIZE: usize = 16;
11
12pub(super) struct ChaCha20Poly1305 {
13    client_key: SealingKey,
14    server_key: OpeningKey,
15}
16
17impl Encryption for ChaCha20Poly1305 {
18    fn bsize(&self) -> usize {
19        BLOCK_SIZE
20    }
21
22    fn iv_size(&self) -> usize {
23        IV_SIZE
24    }
25
26    fn new(hash: Hash, _mac: Box<dyn Mac>) -> ChaCha20Poly1305 {
27        let (ck, sk) = hash.mix_ek(KEY_SIZE);
28        let mut sealing_key = [0_u8; KEY_SIZE];
29        let mut opening_key = [0_u8; KEY_SIZE];
30        sealing_key.copy_from_slice(&ck);
31        opening_key.copy_from_slice(&sk);
32
33        ChaCha20Poly1305 {
34            client_key: SealingKey::new(&sealing_key),
35            server_key: OpeningKey::new(&opening_key),
36        }
37    }
38
39    fn encrypt(&mut self, sequence_number: u32, buf: &mut Vec<u8>) {
40        let mut tag = [0_u8; MAC_SIZE];
41        self.client_key
42            .seal_in_place(sequence_number, buf, &mut tag);
43        buf.append(&mut tag.to_vec());
44    }
45
46    fn decrypt(&mut self, sequence_number: u32, buf: &mut [u8]) -> SshResult<Vec<u8>> {
47        let mut packet_len_slice = [0_u8; 4];
48        let len = &buf[..4];
49        packet_len_slice.copy_from_slice(len);
50        let packet_len_slice = self
51            .server_key
52            .decrypt_packet_length(sequence_number, packet_len_slice);
53        let packet_len = u32::from_be_bytes(packet_len_slice);
54        let (buf, tag_) = buf.split_at_mut((packet_len + 4) as usize);
55        let mut tag = [0_u8; MAC_SIZE];
56        tag.copy_from_slice(tag_);
57        match self.server_key.open_in_place(sequence_number, buf, &tag) {
58            Ok(result) => Ok([&packet_len_slice[..], result].concat()),
59            Err(_) => Err(SshError::EncryptionError(
60                "Failed to decrypt the server traffic".to_owned(),
61            )),
62        }
63    }
64
65    fn packet_len(&mut self, sequence_number: u32, buf: &[u8]) -> usize {
66        let mut packet_len_slice = [0_u8; 4];
67        packet_len_slice.copy_from_slice(&buf[..4]);
68        let packet_len_slice = self
69            .server_key
70            .decrypt_packet_length(sequence_number, packet_len_slice);
71        u32::from_be_bytes(packet_len_slice) as usize + 4
72    }
73
74    fn data_len(&mut self, sequence_number: u32, buf: &[u8]) -> usize {
75        let packet_len = self.packet_len(sequence_number, buf);
76        packet_len + MAC_SIZE
77    }
78
79    fn no_pad(&self) -> bool {
80        true
81    }
82}