aescrypt_rs/decryptor/
session.rs1use crate::aliases::{
8 Aes256Key, EncryptedSessionBlock48, Iv16, PrevCiphertextBlock16, SessionHmacTag32,
9};
10use crate::decryptor::read_exact_span;
11use crate::{crypto::hmac::HmacSha256, error::AescryptError, utils::xor_blocks};
12use aes::cipher::{BlockDecrypt, KeyInit};
13use aes::{Aes256Dec, Block as AesBlock};
14use hmac::Mac;
15use std::io::Read;
16
17#[inline(always)]
24pub fn extract_session_data<R>(
25 reader: &mut R,
26 file_version: u8,
27 public_iv: &Iv16,
28 setup_key: &Aes256Key,
29 session_iv_out: &mut Iv16,
30 session_key_out: &mut Aes256Key,
31) -> Result<(), AescryptError>
32where
33 R: Read,
34{
35 if file_version == 0 {
37 *session_iv_out = Iv16::from(*public_iv.expose_secret());
38 *session_key_out = Aes256Key::from(*setup_key.expose_secret());
39 return Ok(());
40 }
41
42 let encrypted_block: EncryptedSessionBlock48 =
44 EncryptedSessionBlock48::new(read_exact_span(reader)?);
45 let expected_hmac: SessionHmacTag32 = SessionHmacTag32::new(read_exact_span(reader)?);
46
47 let mut mac = <HmacSha256 as Mac>::new_from_slice(setup_key.expose_secret())
49 .expect("setup_key is always 32 bytes — valid HMAC-SHA256 key");
50
51 mac.update(encrypted_block.expose_secret());
52 if file_version >= 3 {
53 mac.update(&[file_version]); }
55
56 if mac.finalize().into_bytes().as_slice() != expected_hmac.expose_secret() {
57 return Err(AescryptError::Header(
58 "session data corrupted or tampered (HMAC mismatch)".into(),
59 ));
60 }
61
62 let cipher = Aes256Dec::new(setup_key.expose_secret().into());
64 let mut previous_block: PrevCiphertextBlock16 =
65 PrevCiphertextBlock16::new(*public_iv.expose_secret());
66
67 for (i, chunk) in encrypted_block.expose_secret().chunks_exact(16).enumerate() {
68 let mut block = *AesBlock::from_slice(chunk);
69 cipher.decrypt_block(&mut block);
70 let decrypted = block.as_slice();
71
72 let target = match i {
73 0 => session_iv_out.expose_secret_mut(),
74 1 => &mut session_key_out.expose_secret_mut()[0..16],
75 2 => &mut session_key_out.expose_secret_mut()[16..32],
76 _ => break,
77 };
78
79 xor_blocks(decrypted, previous_block.expose_secret(), target);
80
81 let mut prev_array = [0u8; 16];
83 prev_array.copy_from_slice(chunk);
84 previous_block = PrevCiphertextBlock16::new(prev_array);
85 }
86
87 Ok(())
88}