1use hmac::Mac as _;
10use sha2::Digest as _;
11
12pub fn md4(data: &[u8]) -> [u8; 16] {
14 let mut h = md4::Md4::new();
15 h.update(data);
16 h.finalize().into()
17}
18
19pub fn md5(data: &[u8]) -> [u8; 16] {
21 let mut h = md5::Md5::new();
22 h.update(data);
23 h.finalize().into()
24}
25
26pub fn hmac_md5(key: &[u8], data: &[u8]) -> [u8; 16] {
28 let mut m = <hmac::Hmac<md5::Md5> as hmac::KeyInit>::new_from_slice(key)
29 .expect("HMAC accepts any key length");
30 m.update(data);
31 m.finalize().into_bytes().into()
32}
33
34pub fn sha256(data: &[u8]) -> [u8; 32] {
36 let mut h = sha2::Sha256::new();
37 h.update(data);
38 h.finalize().into()
39}
40
41pub fn sha512(data: &[u8]) -> [u8; 64] {
43 let mut h = sha2::Sha512::new();
44 h.update(data);
45 h.finalize().into()
46}
47
48pub fn hmac_sha256(key: &[u8], data: &[u8]) -> [u8; 32] {
50 let mut m =
51 <hmac::Hmac<sha2::Sha256> as hmac::KeyInit>::new_from_slice(key).expect("any key length");
52 m.update(data);
53 m.finalize().into_bytes().into()
54}
55
56pub fn rc4(key: &[u8], data: &[u8]) -> Vec<u8> {
59 macro_rules! rc4_dispatch {
62 ($($len:expr => $ty:ident),+ $(,)?) => {
63 match key.len() {
64 $(
65 $len => {{
66 type C = rc4::Rc4<typenum::$ty>;
67 let mut c = <C as rc4::KeyInit>::new_from_slice(key)
68 .expect("length checked by dispatch");
69 let mut out = data.to_vec();
70 use rc4::StreamCipher as _;
71 c.apply_keystream(&mut out);
72 out
73 }}
74 )+
75 n => panic!("rc4: unsupported key length {n} (lib backend supports 1..=64)"),
76 }
77 };
78 }
79 rc4_dispatch! {
80 1 => U1, 2 => U2, 3 => U3, 4 => U4, 5 => U5, 6 => U6, 7 => U7, 8 => U8,
81 9 => U9, 10 => U10, 11 => U11, 12 => U12, 13 => U13, 14 => U14, 15 => U15,
82 16 => U16, 17 => U17, 18 => U18, 19 => U19, 20 => U20, 21 => U21, 22 => U22,
83 23 => U23, 24 => U24, 25 => U25, 26 => U26, 27 => U27, 28 => U28, 29 => U29,
84 30 => U30, 31 => U31, 32 => U32,
85 }
86}
87
88#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] fn key7_to_key8(k7: &[u8; 7]) -> [u8; 8] {
93 let mut bits = [0u8; 56];
94 let mut bit = 0usize;
95 for byte in k7.iter() {
96 for shift in (0..8).rev() {
97 if bit == 56 {
98 break;
99 }
100 bits[bit] = (byte >> shift) & 1;
101 bit += 1;
102 }
103 }
104 let mut out = [0u8; 8];
105 for i in 0..8 {
106 let mut b = 0u8;
107 for j in 0..7 {
108 b |= bits[i * 7 + j] << (7 - j);
109 }
110 out[i] = b; }
112 out
113}
114
115pub fn des_encrypt_key7(key56: [u8; 7], plaintext: [u8; 8]) -> [u8; 8] {
117 let key8 = key7_to_key8(&key56);
118 let cipher = <des::Des as des::cipher::KeyInit>::new_from_slice(&key8)
119 .expect("DES key is exactly 8 bytes");
120 let mut block = des::cipher::Array::from(plaintext);
121 use des::cipher::BlockCipherEncrypt as _;
122 cipher.encrypt_block(&mut block);
123 block.into()
124}
125
126#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn ntlmv1_response(hash21: &[u8; 21], challenge: &[u8; 8]) -> [u8; 24] {
130 let mut out = [0u8; 24];
131 for i in 0..3 {
132 let mut k = [0u8; 7];
133 k.copy_from_slice(&hash21[i * 7..i * 7 + 7]);
134 out[i * 8..i * 8 + 8].copy_from_slice(&des_encrypt_key7(k, *challenge));
135 }
136 out
137}
138
139pub fn aes128_encrypt_block(key: &[u8; 16], block: &[u8; 16]) -> [u8; 16] {
141 let cipher =
142 <aes::Aes128 as aes::cipher::KeyInit>::new_from_slice(key).expect("AES-128 key is 16 bytes");
143 let mut b = aes::cipher::Array::from(*block);
144 use aes::cipher::BlockCipherEncrypt as _;
145 cipher.encrypt_block(&mut b);
146 b.into()
147}
148
149pub fn aes128_cmac(key: &[u8; 16], data: &[u8]) -> [u8; 16] {
151 let mut c =
152 <cmac::Cmac<aes::Aes128> as digest::KeyInit>::new_from_slice(key).expect("any key length");
153 use cmac::digest::Mac as _;
154 c.update(data);
155 c.finalize().into_bytes().into()
156}
157
158pub fn aes128gcm_seal(key: &[u8; 16], nonce: &[u8; 12], aad: &[u8], plaintext: &[u8]) -> Vec<u8> {
164 use aes_gcm::aead::AeadInOut;
165 let c = <aes_gcm::Aes128Gcm as aes_gcm::KeyInit>::new_from_slice(key)
166 .expect("AES-GCM key is exactly 16 bytes");
167 let nonce = aes_gcm::Nonce::from(*nonce);
168 let mut buf = plaintext.to_vec();
169 c.encrypt_in_place(&nonce, aad, &mut buf).expect("GCM seal");
170 buf
171}
172
173#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn aes128gcm_open(
176 key: &[u8; 16],
177 nonce: &[u8; 12],
178 aad: &[u8],
179 ciphertext: &[u8],
180) -> Option<Vec<u8>> {
181 use aes_gcm::aead::AeadInOut;
182 if ciphertext.len() < 16 {
183 return None;
184 }
185 let c = <aes_gcm::Aes128Gcm as aes_gcm::KeyInit>::new_from_slice(key).ok()?;
186 let nonce = aes_gcm::Nonce::from(*nonce);
187 let mut buf = ciphertext.to_vec();
188 c.decrypt_in_place(&nonce, aad, &mut buf).ok()?;
189 Some(buf)
190}
191
192pub fn aes128ccm_seal(key: &[u8; 16], nonce: &[u8; 11], aad: &[u8], plaintext: &[u8]) -> Vec<u8> {
194 use ccm::aead::AeadInOut;
195 type AesCcm = ccm::Ccm<aes::Aes128, typenum::U16, typenum::U11>;
196 let c = <AesCcm as ccm::KeyInit>::new_from_slice(key).expect("key is 16 bytes");
197 let nonce = ccm::Nonce::from(*nonce);
198 let mut buf = plaintext.to_vec();
199 c.encrypt_in_place(&nonce, aad, &mut buf).expect("CCM seal");
200 buf
201}
202
203#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn aes128ccm_open(
206 key: &[u8; 16],
207 nonce: &[u8; 11],
208 aad: &[u8],
209 ciphertext: &[u8],
210) -> Option<Vec<u8>> {
211 use ccm::aead::AeadInOut;
212 if ciphertext.len() < 16 {
213 return None;
214 }
215 type AesCcm = ccm::Ccm<aes::Aes128, typenum::U16, typenum::U11>;
216 let c = <AesCcm as ccm::KeyInit>::new_from_slice(key).ok()?;
217 let nonce = ccm::Nonce::from(*nonce);
218 let mut buf = ciphertext.to_vec();
219 c.decrypt_in_place(&nonce, aad, &mut buf).ok()?;
220 Some(buf)
221}
222
223pub fn aes256gcm_seal(key: &[u8; 32], nonce: &[u8; 12], aad: &[u8], plaintext: &[u8]) -> Vec<u8> {
225 use aes_gcm::aead::AeadInOut;
226 let c = <aes_gcm::Aes256Gcm as aes_gcm::KeyInit>::new_from_slice(key)
227 .expect("AES-256-GCM key is exactly 32 bytes");
228 let nonce = aes_gcm::Nonce::from(*nonce);
229 let mut buf = plaintext.to_vec();
230 c.encrypt_in_place(&nonce, aad, &mut buf).expect("GCM seal");
231 buf
232}
233
234#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn aes256gcm_open(
237 key: &[u8; 32],
238 nonce: &[u8; 12],
239 aad: &[u8],
240 ciphertext: &[u8],
241) -> Option<Vec<u8>> {
242 use aes_gcm::aead::AeadInOut;
243 if ciphertext.len() < 16 {
244 return None;
245 }
246 let c = <aes_gcm::Aes256Gcm as aes_gcm::KeyInit>::new_from_slice(key).ok()?;
247 let nonce = aes_gcm::Nonce::from(*nonce);
248 let mut buf = ciphertext.to_vec();
249 c.decrypt_in_place(&nonce, aad, &mut buf).ok()?;
250 Some(buf)
251}
252
253pub fn aes256ccm_seal(key: &[u8; 32], nonce: &[u8; 11], aad: &[u8], plaintext: &[u8]) -> Vec<u8> {
255 use ccm::aead::AeadInOut;
256 type AesCcm = ccm::Ccm<aes::Aes256, typenum::U16, typenum::U11>;
257 let c = <AesCcm as ccm::KeyInit>::new_from_slice(key).expect("key is 32 bytes");
258 let nonce = ccm::Nonce::from(*nonce);
259 let mut buf = plaintext.to_vec();
260 c.encrypt_in_place(&nonce, aad, &mut buf).expect("CCM seal");
261 buf
262}
263
264#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn aes256ccm_open(
267 key: &[u8; 32],
268 nonce: &[u8; 11],
269 aad: &[u8],
270 ciphertext: &[u8],
271) -> Option<Vec<u8>> {
272 use ccm::aead::AeadInOut;
273 if ciphertext.len() < 16 {
274 return None;
275 }
276 type AesCcm = ccm::Ccm<aes::Aes256, typenum::U16, typenum::U11>;
277 let c = <AesCcm as ccm::KeyInit>::new_from_slice(key).ok()?;
278 let nonce = ccm::Nonce::from(*nonce);
279 let mut buf = ciphertext.to_vec();
280 c.decrypt_in_place(&nonce, aad, &mut buf).ok()?;
281 Some(buf)
282}
283
284#[cfg_attr(dylint_lib = "no_magic_numbers", allow(no_magic_numbers))] pub fn ntlm_mech_list_mic(
293 session_key: &[u8; 16],
294 server_role: bool,
295 key_exch: bool,
296 seq: u32,
297 message: &[u8],
298) -> [u8; 16] {
299 const SRV_SIGN: &[u8] = b"session key to server-to-client signing key magic constant";
300 const CLI_SIGN: &[u8] = b"session key to client-to-server signing key magic constant";
301 const SRV_SEAL: &[u8] = b"session key to server-to-client sealing key magic constant";
302 const CLI_SEAL: &[u8] = b"session key to client-to-server sealing key magic constant";
303
304 let (sign_const, seal_const) =
305 if server_role { (SRV_SIGN, SRV_SEAL) } else { (CLI_SIGN, CLI_SEAL) };
306
307 let mut sk_in = session_key.to_vec();
308 sk_in.extend_from_slice(sign_const);
309 sk_in.push(0);
310 let send_sign_key = md5(&sk_in);
311
312 let mut input = Vec::with_capacity(4 + message.len());
313 input.extend_from_slice(&seq.to_le_bytes());
314 input.extend_from_slice(message);
315 let mut digest = hmac_md5(&send_sign_key, &input);
316
317 if key_exch {
318 let mut seal_in = session_key.to_vec();
319 seal_in.extend_from_slice(seal_const);
320 seal_in.push(0);
321 let send_seal_key = md5(&seal_in);
322 let first8: Vec<u8> = digest[..8].to_vec();
323 let enc = rc4(&send_seal_key, &first8);
324 digest[..8].copy_from_slice(&enc);
325 }
326
327 let mut out = [0u8; 16];
328 out[0..4].copy_from_slice(&[0x01, 0x00, 0x00, 0x00]);
329 out[4..12].copy_from_slice(&digest[..8]);
330 out[12..16].copy_from_slice(&seq.to_le_bytes());
331 out
332}