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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use crate::algorithm::encryption::Encryption;
use crate::algorithm::hash::Hash;
use crate::algorithm::mac::Mac;
use crate::error::SshError;
use crate::SshResult;
use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
use ctr;

type Aes128Ctr64BE = ctr::Ctr64BE<aes::Aes128>;
type Aes192Ctr64BE = ctr::Ctr64BE<aes::Aes192>;
type Aes256Ctr64BE = ctr::Ctr64BE<aes::Aes256>;

const CTR128_KEY_SIZE: usize = 16;
const CTR192_KEY_SIZE: usize = 24;
const CTR256_KEY_SIZE: usize = 32;
const IV_SIZE: usize = 16;
const BLOCK_SIZE: usize = 16;

// extend data for data encryption
struct Extend {
    // hmac
    mac: Box<dyn Mac>,
    ik_c_s: Vec<u8>,
    ik_s_c: Vec<u8>,
}
impl Extend {
    fn from(mac: Box<dyn Mac>, ik_c_s: Vec<u8>, ik_s_c: Vec<u8>) -> Self {
        Extend {
            mac,
            ik_c_s,
            ik_s_c,
        }
    }
}

macro_rules! crate_aes_ctr {
    ($name: ident, $alg: ident, $key_size: expr) => {
        pub(super) struct $name {
            pub(super) client_key: $alg,
            pub(super) server_key: $alg,
            extend: Extend,
        }

        impl Encryption for $name {
            fn bsize(&self) -> usize {
                BLOCK_SIZE
            }

            fn iv_size(&self) -> usize {
                IV_SIZE
            }

            fn new(hash: Hash, mac: Box<dyn Mac>) -> Self
            where
                Self: Sized,
            {
                let (ck, sk) = hash.mix_ek($key_size);
                let mut ckey = [0u8; $key_size];
                let mut skey = [0u8; $key_size];
                ckey.clone_from_slice(&ck[..$key_size]);
                skey.clone_from_slice(&sk[..$key_size]);

                let mut civ = [0u8; IV_SIZE];
                let mut siv = [0u8; IV_SIZE];
                civ.clone_from_slice(&hash.iv_c_s[..IV_SIZE]);
                siv.clone_from_slice(&hash.iv_s_c[..IV_SIZE]);

                let c = $alg::new(&ckey.into(), &civ.into());
                let r = $alg::new(&skey.into(), &siv.into());
                // hmac
                let (ik_c_s, ik_s_c) = hash.mix_ik(mac.bsize());
                $name {
                    client_key: c,
                    server_key: r,
                    extend: Extend::from(mac, ik_c_s, ik_s_c),
                }
            }

            fn encrypt(&mut self, client_sequence_num: u32, buf: &mut Vec<u8>) {
                let tag = self
                    .extend
                    .mac
                    .sign(&self.extend.ik_c_s, client_sequence_num, buf);
                self.client_key.apply_keystream(buf);
                buf.extend(tag.as_ref())
            }

            fn decrypt(
                &mut self,
                server_sequence_number: u32,
                buf: &mut [u8],
            ) -> SshResult<Vec<u8>> {
                let pl = self.packet_len(server_sequence_number, buf);
                let data = &mut buf[..(pl + self.extend.mac.bsize())];
                let (d, m) = data.split_at_mut(pl);
                self.server_key.apply_keystream(d);
                let tag = self
                    .extend
                    .mac
                    .sign(&self.extend.ik_s_c, server_sequence_number, d);
                let t = tag.as_ref();
                if m != t {
                    return Err(SshError::EncryptionError(
                        "Failed to decrypt the server traffic".to_owned(),
                    ));
                }
                Ok(d.to_vec())
            }

            fn packet_len(&mut self, _: u32, buf: &[u8]) -> usize {
                let bsize = self.bsize();
                let mut r = vec![0_u8; bsize];
                r.clone_from_slice(&buf[..bsize]);
                self.server_key.apply_keystream(&mut r);
                let pos: usize = self.server_key.current_pos();
                self.server_key.seek(pos - bsize);
                let packet_len = u32::from_be_bytes(r[..4].try_into().unwrap());
                (packet_len + 4) as usize
            }

            fn data_len(&mut self, server_sequence_number: u32, buf: &[u8]) -> usize {
                let pl = self.packet_len(server_sequence_number, buf);
                let bsize = self.extend.mac.bsize();
                pl + bsize
            }

            fn no_pad(&self) -> bool {
                false
            }
        }
    };
}

// aes-128-ctr
crate_aes_ctr!(Ctr128, Aes128Ctr64BE, CTR128_KEY_SIZE);
// aes-192-ctr
crate_aes_ctr!(Ctr192, Aes192Ctr64BE, CTR192_KEY_SIZE);
// aes-256-ctr
crate_aes_ctr!(Ctr256, Aes256Ctr64BE, CTR256_KEY_SIZE);