#[macro_use] extern crate log;
extern crate crypto;
extern crate hex;
extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use crypto::aes;
use crypto::buffer;
use std::iter::Iterator;
use std::io::Cursor;
extern "C" {
fn aes_xtsn_encrypt(buffer: *mut u8, len: u64, key: *mut u8, tweakin: *mut u8, sectoroffsethi: u64, sectoroffsetlo: u64, sector_size: u32);
fn aes_xtsn_decrypt(buffer: *mut u8, len: u64, key: *mut u8, tweakin: *mut u8, sectoroffsethi: u64, sectoroffsetlo: u64, sector_size: u32);
}
pub struct CXTSN {
crypt: [u8; 0x10], tweak: [u8; 0x10], }
impl CXTSN {
#[must_use]
pub fn new(crypt: &str, tweak: &str) -> Result<Self, String> {
let tcrypt = match hex::decode(crypt) {
Ok(res) => res,
Err(err) => return Err(format!("[l{:03}] Error decoding crypt: {}", line!(), err)),
};
let ttweak = match hex::decode(tweak) {
Ok(res) => res,
Err(err) => return Err(format!("[l{:03}] Error decoding tweak: {}", line!(), err)),
};
debug!("Initialized XTSN struct with the following keys: tcrypt: {:?} and ttweak {:?} ", &tcrypt, &ttweak);
Ok(Self {
crypt: {
let mut array = [0u8; 0x10];
let bytes = &tcrypt.as_slice()[..array.len()]; array.copy_from_slice(bytes);
array
},
tweak: {
let mut array = [0u8; 0x10];
let bytes = &ttweak.as_slice()[..array.len()]; array.copy_from_slice(bytes);
array
},
})
}
#[must_use]
pub fn encrypt(&self, buffer: Vec<u8>, sector_off: usize) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = buffer;
let mut crypt = self.crypt.clone();
let mut tweak = self.tweak.clone();
unsafe {
aes_xtsn_encrypt(
result.as_mut_ptr(),
result.len() as u64,
crypt.as_mut_ptr(),
tweak.as_mut_ptr(),
(sector_off as u64).wrapping_shr(64) & 0xFFFFFFFFFFFFFFFF,
(sector_off as u64) & 0xFFFFFFFFFFFFFFFF,
0x200
);
}
Ok(result)
}
#[must_use]
pub fn decrypt(&self, buffer: Vec<u8>, sector_off: usize) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = buffer;
let mut crypt = self.crypt.clone();
let mut tweak = self.tweak.clone();
unsafe {
aes_xtsn_decrypt(
result.as_mut_ptr(),
result.len() as u64,
crypt.as_mut_ptr(),
tweak.as_mut_ptr(),
(sector_off as u64).wrapping_shr(64) & 0xFFFFFFFFFFFFFFFF,
(sector_off as u64) & 0xFFFFFFFFFFFFFFFF,
0x200
);
}
Ok(result)
}
fn pack(data: u128) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = Vec::new();
match result.write_u128::<LE>(data) {
Ok(res) => res,
Err(err) => return Err(format!("{:?}", err)),
}
while result.len() != 16 {
result.push(0);
}
Ok(result)
}
fn unpack(data: Vec<u8>) -> Result<u128, String> {
let mut rdr = Cursor::new(data);
let result = rdr.read_u128::<LE>();
match result {
Ok(res) => Ok(res),
Err(err) => Err(format!("{:?}", err)),
}
}
fn xor(s1: &Vec<u8>, s2: &Vec<u8>) -> Vec<u8> {
let mut result: Vec<u8> = Vec::new();
for (a, b) in Iterator::zip(s1.iter(), s2.iter()) {
result.push(a ^ b);
}
result
}
}
pub struct XTSN {
crypt: [u8; 0x10], tweak: [u8; 0x10], }
impl XTSN {
#[must_use]
pub fn new(crypt: &str, tweak: &str) -> Result<Self, String> {
let tcrypt = match hex::decode(crypt) {
Ok(res) => res,
Err(err) => return Err(format!("[l{:03}] Error decoding crypt: {}", line!(), err)),
};
let ttweak = match hex::decode(tweak) {
Ok(res) => res,
Err(err) => return Err(format!("[l{:03}] Error decoding tweak: {}", line!(), err)),
};
debug!("Initialized XTSN struct with the following keys: tcrypt: {:?} and ttweak {:?} ", &tcrypt, &ttweak);
Ok(Self {
crypt: {
let mut array = [0u8; 0x10];
let bytes = &tcrypt.as_slice()[..array.len()]; array.copy_from_slice(bytes);
array
},
tweak: {
let mut array = [0u8; 0x10];
let bytes = &ttweak.as_slice()[..array.len()]; array.copy_from_slice(bytes);
array
},
})
}
#[must_use]
pub fn decrypt(&self, buffer: Vec<u8>, sector_off: usize) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = Vec::new();
for i in 0..buffer.len() / 0x200 {
let pos: u128 = (sector_off + i) as u128;
let mut tweak = {
let mut data = match Self::pack(pos) {
Err(err) => return Err(err),
Ok(res) => res,
};
let mut tbuffer = [0u8; 16];
let mut read_buffer = buffer::RefReadBuffer::new(&mut data);
let mut write_buffer = buffer::RefWriteBuffer::new(&mut tbuffer);
let mut c_enc = aes::ecb_encryptor(
aes::KeySize::KeySize128,
&self.tweak,
crypto::blockmodes::NoPadding );
match c_enc.encrypt(&mut read_buffer, &mut write_buffer, true) {
Err(e) => return Err(format!("[l{:03}] Encrypting failed: {:?}", line!(), e)),
_ => {},
};
tbuffer.to_vec()
};
for j in 0..0x200 / 16 {
let off = i * 0x200 + j * 16;
let mut blk = {
let mut tbuffer = [0u8; 16].to_vec();
let mut tblk = Self::xor(&buffer[off..off+16].to_vec(), &tweak);
let mut read_buffer = buffer::RefReadBuffer::new(&mut tblk);
let mut write_buffer = buffer::RefWriteBuffer::new(&mut tbuffer);
let mut dec = aes::ecb_decryptor(
aes::KeySize::KeySize128,
&self.crypt,
crypto::blockmodes::NoPadding
);
match dec.decrypt(&mut read_buffer, &mut write_buffer, true) {
Err(e) => return Err(format!("[l{:03}] Decrypting failed: {:?}", line!(), e)),
_ => {},
};
Self::xor(&tbuffer, &tweak)
};
tweak = {
let mut ttweak = match Self::unpack(tweak.to_vec()) {
Ok(res) => res,
Err(err) => return Err(err),
};
debug!(
"in1: {:0128b}\nin2: {:0128b}\nout: {:0128b}\n---------------------",
ttweak,
1u128.wrapping_shl(127),
ttweak & 1u128.wrapping_shl(127)
);
if ttweak & 1u128.wrapping_shl(127) > 0 {
ttweak = ((ttweak & !1u128.wrapping_shl(127)) << 1) ^ 0x87;
} else {
ttweak <<= 1;
}
match Self::pack(ttweak) {
Ok(res) => res,
Err(err) => return Err(err),
}
};
result.append(&mut blk);
}
}
Ok(result)
}
#[must_use]
pub fn encrypt(&self, buffer: Vec<u8>, sector_off: usize) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = Vec::new();
for i in 0..buffer.len() / 0x200 {
let pos: u128 = (sector_off + i) as u128;
let mut tweak = {
let mut data = match Self::pack(pos) {
Ok(res) => res,
Err(err) => return Err(err),
};
let mut tbuffer = [0u8; 16];
let mut read_buffer = buffer::RefReadBuffer::new(&mut data);
let mut write_buffer = buffer::RefWriteBuffer::new(&mut tbuffer);
let mut c_enc = aes::ecb_encryptor(
aes::KeySize::KeySize128,
&self.crypt,
crypto::blockmodes::NoPadding
);
match c_enc.encrypt(&mut read_buffer, &mut write_buffer, true) {
Err(e) => return Err(format!("[l{:03}] Encrypting failed: {:?}", line!(), e)),
_ => {},
};
tbuffer.to_vec()
};
for j in 0..0x200 / 16 {
let off = i * 0x200 + j * 16;
let mut blk = {
let mut tbuffer = [0u8; 16].to_vec();
let mut tblk = Self::xor(&buffer[off..off+16].to_vec(), &tweak);
let mut read_buffer = buffer::RefReadBuffer::new(&mut tblk);
let mut write_buffer = buffer::RefWriteBuffer::new(&mut tbuffer);
let mut c_dec = aes::ecb_decryptor(
aes::KeySize::KeySize128,
&self.tweak,
crypto::blockmodes::NoPadding
);
match c_dec.decrypt(&mut read_buffer, &mut write_buffer, true) {
Err(e) => return Err(format!("[l{:03}] Decrypting failed: {:?}", line!(), e)),
_ => {},
};
Self::xor(&tbuffer, &tweak)
};
tweak = {
let mut ttweak = match Self::unpack(tweak.to_vec()) {
Ok(res) => res,
Err(err) => return Err(err),
};
debug!(
"in1: {:0128b}\nin2: {:0128b}\nout: {:0128b}\n---------------------",
ttweak,
1u128.wrapping_shl(127),
ttweak & 1u128.wrapping_shl(127)
);
if ttweak & 1u128.wrapping_shl(127) > 0 {
ttweak = ((ttweak & !1u128.wrapping_shl(127)) << 1) ^ 0x87;
} else {
ttweak <<= 1;
}
match Self::pack(ttweak) {
Ok(res) => res,
Err(err) => return Err(err),
}
};
result.append(&mut blk);
}
}
Ok(result)
}
fn pack(data: u128) -> Result<Vec<u8>, String> {
let mut result: Vec<u8> = Vec::new();
match result.write_u128::<LE>(data) {
Ok(res) => res,
Err(err) => return Err(format!("{:?}", err)),
}
while result.len() != 16 {
result.push(0);
}
Ok(result)
}
fn unpack(data: Vec<u8>) -> Result<u128, String> {
let mut rdr = Cursor::new(data);
let result = rdr.read_u128::<LE>();
match result {
Ok(res) => Ok(res),
Err(err) => Err(format!("{:?}", err)),
}
}
fn xor(s1: &Vec<u8>, s2: &Vec<u8>) -> Vec<u8> {
let mut result: Vec<u8> = Vec::new();
for (a, b) in Iterator::zip(s1.iter(), s2.iter()) {
result.push(a ^ b);
}
result
}
}