mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
add tsb bin extractor
This commit is contained in:
@@ -224,5 +224,11 @@ Tip: if you have split ROM (.ROM-00 and .ROM-01), extract both into the same fol
|
||||
**Notes:** **Depends on keys** - see keys.rs (Platforms up to MSB29 are supported)
|
||||
**Thanks to:** http://malcolmstagg.com/bdp/s390-firmware.html
|
||||
|
||||
## TSB Bin
|
||||
**Used in:** Older Toshiba TVs
|
||||
**Notes:** None, all files should be supported.
|
||||
**Options:**
|
||||
※ Support `dump_dec_hdrs` option
|
||||
|
||||
# License
|
||||
Licensed under GNU GPL v3.
|
||||
|
||||
@@ -34,6 +34,7 @@ pub mod cd5;
|
||||
pub mod gx_dvb;
|
||||
pub mod onkyo;
|
||||
pub mod philips_bdp;
|
||||
pub mod tsb_bin;
|
||||
|
||||
pub mod pup;
|
||||
|
||||
@@ -250,5 +251,10 @@ pub fn get_registry() -> Vec<Format> {
|
||||
detector_func: crate::formats::mstar_secure_old::is_mstar_secure_old_file,
|
||||
extractor_func: crate::formats::mstar_secure_old::extract_mstar_secure_old,
|
||||
},
|
||||
Format {
|
||||
name: "tsb_bin",
|
||||
detector_func: crate::formats::tsb_bin::is_tsb_bin_file,
|
||||
extractor_func: crate::formats::tsb_bin::extract_tsb_bin,
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
use crate::utils::common;
|
||||
use binrw::BinRead;
|
||||
|
||||
#[derive(BinRead)]
|
||||
pub struct Header {
|
||||
_signature: [u8; 128],
|
||||
_control_id: u32, //must be zero
|
||||
pub lenght: u32, //file size
|
||||
pub entry_count: u32,
|
||||
_pad1: [u8; 4],
|
||||
build_no_bytes: [u8; 16],
|
||||
_maker_id: u32,
|
||||
_model_id: u32,
|
||||
_group_id: u32,
|
||||
_target_version: u32,
|
||||
pub entry_addr: u32,
|
||||
_pad3: [u8; 12],
|
||||
_tsb_bin_ver: u32, //known is 3
|
||||
_pad4: [u8; 12],
|
||||
_active_flag: u32, //used in NAND to mark the active boot slot
|
||||
_pad5: [u8; 24],
|
||||
_key_component: u32, //used for calculating key for old type "signature"
|
||||
_pad6: [u8; 8],
|
||||
_image_checksum: u32, //sum 256..1024
|
||||
_header_checksum: u32, //sum 0..252
|
||||
#[br(count=entry_count)] pub entries: Vec<Entry>,
|
||||
}
|
||||
impl Header {
|
||||
pub fn build_no(&self) -> String {
|
||||
common::string_from_bytes(&self.build_no_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(BinRead)]
|
||||
pub struct Entry {
|
||||
name_bytes: [u8; 4],
|
||||
image_flag: u32,
|
||||
pub offset: u32,
|
||||
pub size: u32,
|
||||
pub load_addr: u32,
|
||||
_pad1: [u8; 8],
|
||||
_image_checksum: u32,
|
||||
_pad2: [u8; 32],
|
||||
}
|
||||
impl Entry {
|
||||
pub fn name(&self) -> String {
|
||||
common::string_from_bytes(&self.name_bytes)
|
||||
}
|
||||
pub fn is_compressed(&self) -> bool {
|
||||
(self.image_flag & 1 << 4) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid_header_checksum(header_data: &[u8]) -> bool {
|
||||
if header_data.len() < 256 {
|
||||
return false;
|
||||
}
|
||||
|
||||
//calc first sum 63*4 = 252 bytes
|
||||
let calc: u32 = header_data[..252]
|
||||
.chunks_exact(4)
|
||||
.map(|ch| {u32::from_be_bytes(ch.try_into().unwrap())})
|
||||
.fold(0u32, |a, x| a.wrapping_add(x));
|
||||
|
||||
//expected checksum at end
|
||||
let exp = u32::from_be_bytes(header_data[252..256].try_into().unwrap());
|
||||
|
||||
calc == exp
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
mod include;
|
||||
mod tsb_des;
|
||||
use std::any::Any;
|
||||
use crate::AppContext;
|
||||
use crate::utils::compression::decompress_zlib;
|
||||
use crate::utils::global::opt_dump_dec_hdr;
|
||||
|
||||
use std::path::Path;
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::{Cursor, Write};
|
||||
use binrw::BinReaderExt;
|
||||
|
||||
use crate::utils::common;
|
||||
use include::*;
|
||||
use tsb_des::decrypt;
|
||||
|
||||
struct TsbBinCtx {
|
||||
key: Option<[u8; 8]>
|
||||
}
|
||||
|
||||
pub fn is_tsb_bin_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||
|
||||
let header = common::read_file(&file, 0, 256)?;
|
||||
if is_valid_header_checksum(&header) {
|
||||
return Ok(Some(Box::new(TsbBinCtx {key: None})));
|
||||
}
|
||||
|
||||
// -- failed, try with decrypt
|
||||
//derive key from FILE SIZE (yes)
|
||||
let file_size = file.metadata()?.len() as u32;
|
||||
let mut key = [0u8; 8];
|
||||
key[..4].copy_from_slice(&file_size.to_le_bytes());
|
||||
let inv = !file_size;
|
||||
key[4..].copy_from_slice(&inv.to_le_bytes());
|
||||
|
||||
let dec_header = decrypt(&header, &key);
|
||||
if is_valid_header_checksum(&dec_header) {
|
||||
Ok(Some(Box::new(TsbBinCtx {key: Some(key)})))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_tsb_bin(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||
let ctx = ctx.downcast::<TsbBinCtx>().expect("Missing context");
|
||||
|
||||
let mut header = common::read_file(&mut file, 0, 0x400)?;
|
||||
if let Some(key) = ctx.key { //decrypt header
|
||||
println!("File is encrypted, using key: {}", hex::encode(&key));
|
||||
header = decrypt(&header, &key);
|
||||
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||
}
|
||||
|
||||
let mut hdr_rdr = Cursor::new(header);
|
||||
let hdr: Header = hdr_rdr.read_be()?;
|
||||
|
||||
println!("File info -\nSize: {}\nEntry count: {}\nBuild no.: {}\nEntry address: 0x{:02x}"
|
||||
,hdr.lenght, hdr.entry_count, hdr.build_no(), hdr.entry_addr);
|
||||
|
||||
for (i, entry) in hdr.entries.iter().enumerate() {
|
||||
println!("\n({}/{}) - {}, Size: {}, Offset: {}, Load address: 0x{:02x}",
|
||||
i+1, hdr.entry_count, entry.name(), entry.size, entry.offset, entry.load_addr);
|
||||
|
||||
let mut data;
|
||||
if let Some(key) = ctx.key {
|
||||
let enc_data = common::read_file(&mut file, entry.offset as u64, (entry.size as usize + 7) & !7)?; //read aligned to 8b blocks for decryption
|
||||
println!("- Decrypting...");
|
||||
data = decrypt(&enc_data, &key);
|
||||
data.truncate(entry.size as usize); //discard alignment
|
||||
|
||||
} else {
|
||||
data = common::read_file(&mut file, entry.offset as u64, entry.size as usize)?;
|
||||
}
|
||||
|
||||
if entry.is_compressed() {
|
||||
println!("- Decompressing...");
|
||||
data = decompress_zlib(&data)?;
|
||||
}
|
||||
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", entry.name()));
|
||||
|
||||
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||
let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?;
|
||||
out_file.write_all(&data)?;
|
||||
|
||||
println!("-- Saved file!");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
// Source: github.com/antoyo/des-rs
|
||||
// The des() function has been modified to work with Toshiba variant
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
pub type Key = [u8; 8];
|
||||
|
||||
const FIRST_BIT: u64 = 1 << 63;
|
||||
const HALF_KEY_SIZE: i64 = KEY_SIZE / 2;
|
||||
const KEY_SIZE: i64 = 56;
|
||||
|
||||
/// Do a circular left shift on a width of `HALF_KEY_SIZE`.
|
||||
fn circular_left_shift(n1: u64, n2: u64, shift_count: i64) -> (u64, u64) {
|
||||
let mut new_value1 = n1;
|
||||
let mut new_value2 = n2;
|
||||
for _ in 0 .. shift_count {
|
||||
let first_bit = new_value1 & FIRST_BIT;
|
||||
new_value1 = (new_value1 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||
let first_bit = new_value2 & FIRST_BIT;
|
||||
new_value2 = (new_value2 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||
}
|
||||
(new_value1, new_value2)
|
||||
}
|
||||
|
||||
/// Create the 16 subkeys.
|
||||
fn compute_subkeys(key: u64) -> Vec<u64> {
|
||||
let table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
|
||||
let k0 = pc1(key);
|
||||
let mut subkeys = vec![k0];
|
||||
|
||||
for shift_count in &table {
|
||||
let last_key = *subkeys.last().unwrap();
|
||||
let last_ci = last_key & 0xFFFFFFF000000000;
|
||||
let last_di = last_key << HALF_KEY_SIZE;
|
||||
let (ci, di) = circular_left_shift(last_ci, last_di, *shift_count);
|
||||
let current_key = ci | (di >> HALF_KEY_SIZE);
|
||||
subkeys.push(current_key);
|
||||
}
|
||||
|
||||
subkeys.remove(0);
|
||||
subkeys.iter().map(|&n| { pc2(n) }).collect()
|
||||
}
|
||||
|
||||
/// Decrypt `message` using the `key`.
|
||||
pub fn decrypt(cipher: &[u8], key: &Key) -> Vec<u8> {
|
||||
let key = key_to_u64(key);
|
||||
let mut subkeys = compute_subkeys(key);
|
||||
subkeys.reverse();
|
||||
des(cipher, subkeys)
|
||||
}
|
||||
|
||||
/// Swap bits in `a` using a delta swap.
|
||||
fn delta_swap(a: u64, delta: u64, mask: u64) -> u64 {
|
||||
let b = (a ^ (a >> delta)) & mask;
|
||||
a ^ b ^ (b << delta)
|
||||
}
|
||||
|
||||
|
||||
/// Encrypt `message` using `subkeys`.
|
||||
fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
|
||||
let message_len = message.len();
|
||||
let message = message_to_u64s(message);
|
||||
|
||||
let mut blocks = vec![];
|
||||
|
||||
blocks = message.iter().map(|&block| {
|
||||
let permuted = ip(block);
|
||||
let mut li = permuted & 0xFFFFFFFF00000000;
|
||||
let mut ri = permuted << 32;
|
||||
|
||||
for subkey in &subkeys { // SWAPPED - in toshiba, the feistel function is used on the LEFT half
|
||||
let last_ri = ri;
|
||||
ri = li;
|
||||
li = last_ri ^ feistel(li, *subkey);
|
||||
}
|
||||
|
||||
let r16l16 = li | (ri >> 32); // SWAPPED - order swapped in toshiba
|
||||
to_u8_vec(fp(r16l16))
|
||||
}).collect();
|
||||
|
||||
let mut result = Vec::with_capacity(message_len);
|
||||
for mut block in blocks.into_iter() {
|
||||
result.append(&mut block);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Swap bits using the E table.
|
||||
fn e(block: u64) -> u64 {
|
||||
const BLOCK_LEN: usize = 32;
|
||||
const RESULT_LEN: usize = 48;
|
||||
|
||||
let b1 = (block << (BLOCK_LEN - 1)) & 0x8000000000000000;
|
||||
let b2 = (block >> 1) & 0x7C00000000000000;
|
||||
let b3 = (block >> 3) & 0x03F0000000000000;
|
||||
let b4 = (block >> 5) & 0x000FC00000000000;
|
||||
let b5 = (block >> 7) & 0x00003F0000000000;
|
||||
let b6 = (block >> 9) & 0x000000FC00000000;
|
||||
let b7 = (block >> 11) & 0x00000003F0000000;
|
||||
let b8 = (block >> 13) & 0x000000000FC00000;
|
||||
let b9 = (block >> 15) & 0x00000000003E0000;
|
||||
let b10 = (block >> (RESULT_LEN - 1)) & 0x0000000000010000;
|
||||
b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10
|
||||
}
|
||||
|
||||
/// Encrypt `message` using the `key`.
|
||||
pub fn _encrypt(message: &[u8], key: &Key) -> Vec<u8> {
|
||||
let key = key_to_u64(key);
|
||||
let subkeys = compute_subkeys(key);
|
||||
des(message, subkeys)
|
||||
}
|
||||
|
||||
/// Feistel function.
|
||||
fn feistel(half_block: u64, subkey: u64) -> u64 {
|
||||
let expanded = e(half_block);
|
||||
let mut intermediate = expanded ^ subkey;
|
||||
let mut result = 0;
|
||||
|
||||
for i in 0 .. 8 {
|
||||
let block = (intermediate & 0xFC00000000000000) >> 58;
|
||||
intermediate <<= 6;
|
||||
result <<= 4;
|
||||
result |= s(i, block);
|
||||
}
|
||||
|
||||
p(result << 32)
|
||||
}
|
||||
|
||||
/// Swap bits using the reverse FP table.
|
||||
fn fp(message: u64) -> u64 {
|
||||
let message = delta_swap(message, 24, 0x000000FF000000FF);
|
||||
let message = delta_swap(message, 24, 0x00000000FF00FF00);
|
||||
let message = delta_swap(message, 36, 0x000000000F0F0F0F);
|
||||
let message = delta_swap(message, 18, 0x0000333300003333);
|
||||
delta_swap(message, 9, 0x0055005500550055)
|
||||
}
|
||||
|
||||
/// Swap bits using the IP table.
|
||||
fn ip(message: u64) -> u64 {
|
||||
let message = delta_swap(message, 9, 0x0055005500550055);
|
||||
let message = delta_swap(message, 18, 0x0000333300003333);
|
||||
let message = delta_swap(message, 36, 0x000000000F0F0F0F);
|
||||
let message = delta_swap(message, 24, 0x00000000FF00FF00);
|
||||
delta_swap(message, 24, 0x000000FF000000FF)
|
||||
}
|
||||
|
||||
/// Convert a `Key` to a 64-bits integer.
|
||||
fn key_to_u64(key: &Key) -> u64 {
|
||||
let mut result = 0;
|
||||
for &part in key {
|
||||
result <<= 8;
|
||||
result += part as u64;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Convert a message to a vector of 64-bits integer.
|
||||
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
|
||||
message.chunks(8)
|
||||
.map(|m| key_to_u64(&to_key(m)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Swap bits using the P table.
|
||||
fn p(block: u64) -> u64 {
|
||||
let block = block.rotate_left(44);
|
||||
let b1 = (block & 0x0000000000200000) << 32;
|
||||
let b2 = (block & 0x0000000000480000) << 13;
|
||||
let b3 = (block & 0x0000088000000000) << 12;
|
||||
let b4 = (block & 0x0000002020120000) << 25;
|
||||
let b5 = (block & 0x0000000442000000) << 14;
|
||||
let b6 = (block & 0x0000000001800000) << 37;
|
||||
let b7 = (block & 0x0000000004000000) << 24;
|
||||
let b8 = (block & 0x0000020280015000).wrapping_mul(0x0000020080800083) & 0x02000a6400000000;
|
||||
let b9 = (block.rotate_left(29) & 0x01001400000000aa).wrapping_mul(0x0000210210008081) & 0x0902c01200000000;
|
||||
let b10 = (block & 0x0000000910040000).wrapping_mul(0x0000000c04000020) & 0x8410010000000000;
|
||||
b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10
|
||||
}
|
||||
|
||||
/// Swap bits using the PC-1 table.
|
||||
fn pc1(key: u64) -> u64 {
|
||||
let key = delta_swap(key, 2, 0x3333000033330000);
|
||||
let key = delta_swap(key, 4, 0x0f0f0f0f00000000);
|
||||
let key = delta_swap(key, 8, 0x009a000a00a200a8);
|
||||
let key = delta_swap(key, 16, 0x00006c6c0000cccc);
|
||||
let key = delta_swap(key, 1, 0x1045500500550550);
|
||||
let key = delta_swap(key, 32, 0x00000000f0f0f5fa);
|
||||
let key = delta_swap(key, 8, 0x00550055006a00aa);
|
||||
let key = delta_swap(key, 2, 0x0000333330000300);
|
||||
key & 0xFFFFFFFFFFFFFF00
|
||||
}
|
||||
|
||||
/// Swap bits using the PC-2 table.
|
||||
fn pc2(key: u64) -> u64 {
|
||||
let key = key.rotate_left(61);
|
||||
let b1 = (key & 0x0021000002000000) >> 7;
|
||||
let b2 = (key & 0x0008020010080000) << 1;
|
||||
let b3 = key & 0x0002200000000000;
|
||||
let b4 = (key & 0x0000000000100020) << 19;
|
||||
let b5 = (key.rotate_left(54) & 0x0005312400000011).wrapping_mul(0x0000000094200201) & 0xea40100880000000;
|
||||
let b6 = (key.rotate_left(7) & 0x0022110000012001).wrapping_mul(0x0001000000610006) & 0x1185004400000000;
|
||||
let b7 = (key.rotate_left(6) & 0x0000520040200002).wrapping_mul(0x00000080000000c1) & 0x0028811000200000;
|
||||
let b8 = (key & 0x01000004c0011100).wrapping_mul(0x0000000000004284) & 0x0400082244400000;
|
||||
let b9 = (key.rotate_left(60) & 0x0000000000820280).wrapping_mul(0x0000000000089001) & 0x0000000110880000;
|
||||
let b10 = (key.rotate_left(49) & 0x0000000000024084).wrapping_mul(0x0000000002040005) & 0x000000000a030000;
|
||||
b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10
|
||||
}
|
||||
|
||||
/// Produce 4-bits using an S box.
|
||||
fn s(box_id: usize, block: u64) -> u64 {
|
||||
const TABLES: [[[u64; 16]; 4]; 8] =
|
||||
[[[ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7]
|
||||
, [ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8]
|
||||
, [ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0]
|
||||
, [ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
|
||||
],
|
||||
[ [ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10]
|
||||
, [ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5]
|
||||
, [ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15]
|
||||
, [ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
|
||||
],
|
||||
[ [ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8]
|
||||
, [ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1]
|
||||
, [ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7]
|
||||
, [ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
|
||||
],
|
||||
[ [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15]
|
||||
, [ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9]
|
||||
, [ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4]
|
||||
, [ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
|
||||
],
|
||||
[ [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9]
|
||||
, [ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6]
|
||||
, [ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14]
|
||||
, [ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
|
||||
],
|
||||
[ [ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11]
|
||||
, [ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8]
|
||||
, [ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6]
|
||||
, [ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
|
||||
],
|
||||
[ [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1]
|
||||
, [ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6]
|
||||
, [ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2]
|
||||
, [ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
|
||||
],
|
||||
[ [ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7]
|
||||
, [ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2]
|
||||
, [ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8]
|
||||
, [ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
|
||||
]];
|
||||
let i = ((block & 0x20) >> 4 | (block & 1)) as usize;
|
||||
let j = ((block & 0x1E) >> 1) as usize;
|
||||
// TODO: use get_unchecked().
|
||||
TABLES[box_id][i][j]
|
||||
}
|
||||
|
||||
/// Convert a slice to a `Key`.
|
||||
fn to_key(slice: &[u8]) -> Key {
|
||||
let mut vec: Vec<u8> = slice.iter().cloned().collect();
|
||||
let mut key = [0; 8];
|
||||
let diff = key.len() - vec.len();
|
||||
if diff > 0 {
|
||||
vec.append(&mut vec![0; diff]);
|
||||
}
|
||||
key.clone_from_slice(&vec);
|
||||
key
|
||||
}
|
||||
|
||||
/// Convert a `u64` to a `Vec<u8>`.
|
||||
fn to_u8_vec(num: u64) -> Vec<u8> {
|
||||
vec!
|
||||
[ ((num & 0xFF00000000000000) >> 56) as u8
|
||||
, ((num & 0x00FF000000000000) >> 48) as u8
|
||||
, ((num & 0x0000FF0000000000) >> 40) as u8
|
||||
, ((num & 0x000000FF00000000) >> 32) as u8
|
||||
, ((num & 0x00000000FF000000) >> 24) as u8
|
||||
, ((num & 0x0000000000FF0000) >> 16) as u8
|
||||
, ((num & 0x000000000000FF00) >> 8) as u8
|
||||
, (num & 0x00000000000000FF) as u8
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user