ssh/algorithm/encryption/
aes_ctr.rs1use 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
19struct Extend {
21 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 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
134crate_aes_ctr!(Ctr128, Aes128Ctr64BE, CTR128_KEY_SIZE);
136crate_aes_ctr!(Ctr192, Aes192Ctr64BE, CTR192_KEY_SIZE);
138crate_aes_ctr!(Ctr256, Aes256Ctr64BE, CTR256_KEY_SIZE);