use aes::cipher::{block_padding::NoPadding, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; use anyhow::{anyhow, Result}; type Aes128CbcDec = cbc::Decryptor; type Aes128CbcEnc = cbc::Encryptor; pub const ICF_KEY: [u8; 16] = hex_literal::decode(&[env!("ICF_KEY").as_bytes()]); pub const ICF_IV: [u8; 16] = hex_literal::decode(&[env!("ICF_IV").as_bytes()]); /// Decrypts an ICF using the provided key and IV. pub fn decrypt_icf( data: &mut [u8], key: impl AsRef<[u8]>, iv: impl AsRef<[u8]>, ) -> Result> { let size = data.len(); let mut decrypted = Vec::with_capacity(size); for i in (0..size).step_by(4096) { let from_start = i; let bufsz = std::cmp::min(4096, size - from_start); let buf = &data[i..i + bufsz]; let mut decbuf = vec![0; bufsz]; let cipher = Aes128CbcDec::new_from_slices(key.as_ref(), iv.as_ref())?; cipher .decrypt_padded_b2b_mut::(buf, &mut decbuf) .map_err(|err| anyhow!(err))?; let xor1 = u64::from_le_bytes(decbuf[0..8].try_into()?) ^ (from_start as u64); let xor2 = u64::from_le_bytes(decbuf[8..16].try_into()?) ^ (from_start as u64); decrypted.extend(xor1.to_le_bytes()); decrypted.extend(xor2.to_le_bytes()); decrypted.extend(&decbuf[16..]); } Ok(decrypted) } /// Encrypts an ICF using the provided key and IV. pub fn encrypt_icf(data: &[u8], key: impl AsRef<[u8]>, iv: impl AsRef<[u8]>) -> Result> { let size = data.len(); let mut encrypted = Vec::with_capacity(size); let mut to_be_encrypted = Vec::with_capacity(std::cmp::min(4096, size)); for i in (0..size).step_by(4096) { let from_start = i; let bufsz = std::cmp::min(4096, size - from_start); let buf = &data[i..i + bufsz]; let mut encbuf = vec![0; bufsz]; let xor1 = u64::from_le_bytes(buf[0..8].try_into()?) ^ (from_start as u64); let xor2 = u64::from_le_bytes(buf[8..16].try_into()?) ^ (from_start as u64); to_be_encrypted.extend(xor1.to_le_bytes()); to_be_encrypted.extend(xor2.to_le_bytes()); to_be_encrypted.extend(&buf[16..]); let cipher = Aes128CbcEnc::new_from_slices(key.as_ref(), iv.as_ref())?; cipher .encrypt_padded_b2b_mut::(&to_be_encrypted, &mut encbuf) .map_err(|err| anyhow!(err))?; encrypted.extend(encbuf); to_be_encrypted.clear(); } Ok(encrypted) }