ssh/algorithm/encryption/
aes_ctr.rs

1use crate::algorithm::encryption::Encryption;
2use crate::algorithm::hash::Hash;
3use crate::algorithm::mac::Mac;
4use crate::error::SshError;
5use crate::SshResult;
6use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
7use ctr;
8
9type Aes128Ctr64BE = ctr::Ctr64BE<aes::Aes128>;
10type Aes192Ctr64BE = ctr::Ctr64BE<aes::Aes192>;
11type Aes256Ctr64BE = ctr::Ctr64BE<aes::Aes256>;
12
13const CTR128_KEY_SIZE: usize = 16;
14const CTR192_KEY_SIZE: usize = 24;
15const CTR256_KEY_SIZE: usize = 32;
16const IV_SIZE: usize = 16;
17const BLOCK_SIZE: usize = 16;
18
19// extend data for data encryption
20struct Extend {
21    // hmac
22    mac: Box<dyn Mac>,
23    ik_c_s: Vec<u8>,
24    ik_s_c: Vec<u8>,
25}
26impl Extend {
27    fn from(mac: Box<dyn Mac>, ik_c_s: Vec<u8>, ik_s_c: Vec<u8>) -> Self {
28        Extend {
29            mac,
30            ik_c_s,
31            ik_s_c,
32        }
33    }
34}
35
36macro_rules! crate_aes_ctr {
37    ($name: ident, $alg: ident, $key_size: expr) => {
38        pub(super) struct $name {
39            pub(super) client_key: $alg,
40            pub(super) server_key: $alg,
41            extend: Extend,
42        }
43
44        impl Encryption for $name {
45            fn bsize(&self) -> usize {
46                BLOCK_SIZE
47            }
48
49            fn iv_size(&self) -> usize {
50                IV_SIZE
51            }
52
53            fn new(hash: Hash, mac: Box<dyn Mac>) -> Self
54            where
55                Self: Sized,
56            {
57                let (ck, sk) = hash.mix_ek($key_size);
58                let mut ckey = [0u8; $key_size];
59                let mut skey = [0u8; $key_size];
60                ckey.clone_from_slice(&ck[..$key_size]);
61                skey.clone_from_slice(&sk[..$key_size]);
62
63                let mut civ = [0u8; IV_SIZE];
64                let mut siv = [0u8; IV_SIZE];
65                civ.clone_from_slice(&hash.iv_c_s[..IV_SIZE]);
66                siv.clone_from_slice(&hash.iv_s_c[..IV_SIZE]);
67
68                let c = $alg::new(&ckey.into(), &civ.into());
69                let r = $alg::new(&skey.into(), &siv.into());
70                // hmac
71                let (ik_c_s, ik_s_c) = hash.mix_ik(mac.bsize());
72                $name {
73                    client_key: c,
74                    server_key: r,
75                    extend: Extend::from(mac, ik_c_s, ik_s_c),
76                }
77            }
78
79            fn encrypt(&mut self, client_sequence_num: u32, buf: &mut Vec<u8>) {
80                let tag = self
81                    .extend
82                    .mac
83                    .sign(&self.extend.ik_c_s, client_sequence_num, buf);
84                self.client_key.apply_keystream(buf);
85                buf.extend(tag.as_ref())
86            }
87
88            fn decrypt(
89                &mut self,
90                server_sequence_number: u32,
91                buf: &mut [u8],
92            ) -> SshResult<Vec<u8>> {
93                let pl = self.packet_len(server_sequence_number, buf);
94                let data = &mut buf[..(pl + self.extend.mac.bsize())];
95                let (d, m) = data.split_at_mut(pl);
96                self.server_key.apply_keystream(d);
97                let tag = self
98                    .extend
99                    .mac
100                    .sign(&self.extend.ik_s_c, server_sequence_number, d);
101                let t = tag.as_ref();
102                if m != t {
103                    return Err(SshError::EncryptionError(
104                        "Failed to decrypt the server traffic".to_owned(),
105                    ));
106                }
107                Ok(d.to_vec())
108            }
109
110            fn packet_len(&mut self, _: u32, buf: &[u8]) -> usize {
111                let bsize = self.bsize();
112                let mut r = vec![0_u8; bsize];
113                r.clone_from_slice(&buf[..bsize]);
114                self.server_key.apply_keystream(&mut r);
115                let pos: usize = self.server_key.current_pos();
116                self.server_key.seek(pos - bsize);
117                let packet_len = u32::from_be_bytes(r[..4].try_into().unwrap());
118                (packet_len + 4) as usize
119            }
120
121            fn data_len(&mut self, server_sequence_number: u32, buf: &[u8]) -> usize {
122                let pl = self.packet_len(server_sequence_number, buf);
123                let bsize = self.extend.mac.bsize();
124                pl + bsize
125            }
126
127            fn no_pad(&self) -> bool {
128                false
129            }
130        }
131    };
132}
133
134// aes-128-ctr
135crate_aes_ctr!(Ctr128, Aes128Ctr64BE, CTR128_KEY_SIZE);
136// aes-192-ctr
137crate_aes_ctr!(Ctr192, Aes192Ctr64BE, CTR192_KEY_SIZE);
138// aes-256-ctr
139crate_aes_ctr!(Ctr256, Aes256Ctr64BE, CTR256_KEY_SIZE);