From 51c9a668ec0cb3a674f1aa301fed8a69a1970c00 Mon Sep 17 00:00:00 2001 From: theubusu <80545678+theubusu@users.noreply.github.com> Date: Wed, 8 Oct 2025 15:14:53 +0200 Subject: [PATCH] move keys to seperate keys file, cleanup samsung_old --- TODO.md | 9 +----- src/formats/epk2.rs | 10 ++----- src/formats/msd10.rs | 10 ++----- src/formats/msd11.rs | 14 ++------- src/formats/mstar.rs | 1 + src/formats/pfl_upg.rs | 12 ++------ src/formats/samsung_old.rs | 57 ++++++++++++++++-------------------- src/keys.rs | 60 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + 9 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 src/keys.rs diff --git a/TODO.md b/TODO.md index df57127..9d56610 100644 --- a/TODO.md +++ b/TODO.md @@ -8,11 +8,4 @@ - Samsung MSD10(Legacy and Tizen 2015) - Complete - Samsung MSD11(Tizen 2016+) - Complete - Panasonic SDDL.SEC(2011+) - Complete -- LG Epk2 (Crypted and plain header)- Should be complete, but needs some more testing - -# TODO -- implement some key storing system instead of hardcoding -- cleanup some formats especially mstar and samsung old -- cleanup main file -- Do more testing for PFL UPG and Epk2 -- Epk3? +- LG Epk2 (Crypted and plain header)- Should be complete, but needs some more testing \ No newline at end of file diff --git a/src/formats/epk2.rs b/src/formats/epk2.rs index bd5f3eb..9cb34cd 100644 --- a/src/formats/epk2.rs +++ b/src/formats/epk2.rs @@ -6,6 +6,7 @@ use aes::Aes128; use ecb::{Decryptor, cipher::{BlockDecryptMut, KeyInit, generic_array::GenericArray}}; use crate::common; +use crate::keys; pub fn is_epk2_file(file: &File) -> bool { let header = common::read_file(&file, 128, 4).expect("Failed to read from file."); @@ -22,15 +23,8 @@ struct Pak { name: String, } -static KEYS: &[(&str, &str)] = &[ - ("Saturn7/BCM3556", "2F2E2D2C2B2A29281716151413121110"), - ("new BCM35230", "6856A0482475A8B41728A35474810203"), - ("mtk5369 - Mediatek GP4", "7184C9C428D03C445188234D5A827196"), - ("mtk5398 (a2) - Mediatek NetCast 4/4.5", "385A992430196A8C44F1985823C01440"), -]; - fn find_key<'a>(data: &[u8], expected_magic: &[u8]) -> Result)>, Box> { - for (name, key_hex) in KEYS { + for (key_hex, name) in keys::EPK2 { let key_bytes = hex::decode(key_hex)?; let decrypted = match decrypt_aes128_ecb(&key_bytes, data) { Ok(d) => d, diff --git a/src/formats/msd10.rs b/src/formats/msd10.rs index 5936f4c..ec19442 100644 --- a/src/formats/msd10.rs +++ b/src/formats/msd10.rs @@ -8,6 +8,7 @@ use cbc::{Decryptor, cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit}} type Aes128CbcDec = Decryptor; use crate::common; +use crate::keys; pub fn is_msd10_file(file: &File) -> bool { let header = common::read_file(&file, 0, 6).expect("Failed to read from file."); @@ -25,13 +26,6 @@ struct Section { name: String, } -//fw name, type, key -static KEYS: &[(&str, &str, &str)] = &[ - ("T-NT14M", "old", "95d01e0bae861a05695bc8a6edb2ea835a09accd"), - ("T-HKM", "tizen", "1ac8989ff57db5e75ea67b033050871c"), - ("T-HKP", "tizen", "cce8a3ef92f3e94895999e928f4dd6c3"), -]; - fn decrypt_aes_salted_old(encrypted_data: &[u8], passphrase_bytes: &Vec) -> Result, Box> { let mut data = encrypted_data.to_vec(); @@ -148,7 +142,7 @@ pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box; use crate::common; +use crate::keys; pub fn is_msd11_file(file: &File) -> bool { let header = common::read_file(&file, 0, 6).expect("Failed to read from file."); @@ -25,17 +26,6 @@ struct Section { name: String, } -static KEYS: &[(&str, &str)] = &[ - ("T-JZM", "9b1d077c0d137d406c79ddacb6b159fe"), //2015 - ("T-HKMFK", "c7097975e8ab994beb5eaae57e0ba77c"), //2016 - ("T-KTM2L", "46b04f5e794ca4377a20951c9ea00427"), //2018 - ("T-KTM2", "29110e0ce940b3a9b67d3e158f3f1342"), //2018 - ("T-KTM", "d0d49d5f36f5c0da50062fbf32168f5b"), //2017 - ("T-KTSU", "19e1ba41163f03735e692d9daa2cbb47"), //2018 - ("T-KTSD", "39332605ff47a0aea999b10ce9087389"), //2018 - ("T-NKL", "5bab1098dab48792619ebd63650d929f"), //2020 -]; - fn decrypt_aes_salted_tizen(encrypted_data: &[u8], passphrase_bytes: &Vec) -> Result, Box> { let mut data = encrypted_data.to_vec(); @@ -125,7 +115,7 @@ pub fn extract_msd11(mut file: &File, output_folder: &str) -> Result<(), Box Result<(), Box bool { let header = common::read_file(&file, 0, 8).expect("Failed to read from file."); @@ -19,15 +20,6 @@ pub fn is_pfl_upg_file(file: &File) -> bool { } } -static KEYS: &[(&str, &str)] = &[ - ("q5551", "D7EE8ED11AC048ED225D4F5F53F8509E55C5D94256A703C79E4CA78AE93ECE1639FE466363AD962BD6D6DE0C46FD19F363687C1D8A21820740A6E7FF87F41C4900DCE1E26EC122E5D4DFA76BFC8F296816B8D0910325E9DC5CBCC9579CF15FC0253EF7CF4919B7613491A5D7BF75DC1888531C458967FD1CF64B33139550BAA5"), - ("qf1eu", "ACD684155C7CCCB04372A8808514489FA9EE75D305987D1337420241FDBE0AE1F7CDFBB931C9D56C91D36F2CE79D222695B484FF42BCA12CE362C7C9ABBDEEC8E5D6107FADCF2D4DA5DF0693E13ACE54A18AEB21C051F6B62C075A1791985547C1CFF4FB5B6EA7E0A9405A1B2BB71EB89A9B209E0F62BF9794D673179C0E60F1"), - ("q591e", "AFAF89062747CBB29343C4E4EA775E4CFDF5FAFCD92C9DD858A8725201BA54AB973BEFEE04EBF3046910FBBC78B10120AE16D80BA734931E97248BC6B1D4A909F087D37BC0A9C2210FF8A2BE44C00F31E4DD8713A364623637FF75EBBCE9D3A840DB67E0FA910F127F679496F6C21112E3E3AD4ACA459FDE1CC58E300682E6F9"), - ("q522e", "C41BE92C212BAC76B48261E2A1704028287DD7E121C11DA25F709E864FBDC1BD8C7F226F57605A4B42D768CDD629AF9E54011A0967AFC2826331406FB1E90321620738526EA0BEA59F1A0E612AE891C396112F13531F423DF02F94D1C871429549F4D5B30D9CA3EFDCC6D7A96849F7C1788DE8FAAEDD36560337008DF06D612F"), - ("q5481", "9E7DA389815251E82A84A1182807702E72A0B0E0FF707C8E73E2EA71F79D5FAAFFC6E0B90ED16E13A4289C78A7D3BDA90626162AAE169D7BE28D6A635585CC10639C4E312E288EB8F7C5A44518B7E8A26A45C5023C5078A972A4CC219CA020BAF524F7429257B7AD76E1B15390879064C6ED59CC1F20CC04EEC26C9CF7FC0727"), - ("q5431", "C5FD937B301A5CEF4B6C25F187728C99636515D058895FEA469496E2B24907FC7721648841F8AE4C618E215673D0C029752FA970B6F9A7F48C9331293D3B1D43E4DFC7B52914973642CD3E4EE0AD11F5254505038F95CACE0DF21FC769B34E134435D88AB617D2981F66EF45BBC7796CFB1086C5D5672E837204991FE53BC1CF"), -]; - static AUTO_FWS: &[(&str, &str)] = &[ ("Q5551", "q5551"), ("Q5553", "q5551"), @@ -109,7 +101,7 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box; use crate::common; +use crate::keys; use md5; @@ -43,36 +45,21 @@ pub fn extract_samsung_old(path: &PathBuf, output_folder: &str) -> Result<(), Bo println!("Firmware info: {}", fw_info); let image_path = Path::new(&path).join("image"); - let mut secret = ""; - let secret_t_ecp = [0x3E, 0xF6, 0x06, 0x72, 0x62, 0xCF, 0x0C, 0x67, 0x85, 0x98, 0xBF, 0xF2, 0x21, 0x69, 0xD1, 0xF1, 0xEA, 0x57, 0xC2, 0x84]; - // from samygo tool - if fw_info.starts_with("T-GA"){ - secret = "SHWJUH:85a045ae-2296-484c-b457-ede832fcfbe1-646390a3-105e-40aa-85f6-da3086c70111"; - } else if fw_info.starts_with("T-MST5"){ - secret = "SHWJUH:eceb2c14-db11-425e-9ebf-5f9607f0eb4b-3c38193e-751e-4719-8884-9e76322c0cec"; - } else if fw_info.starts_with("B-FIRHT7"){ - secret = "d6442d-7b46b2f4-0f11-4623-af63-8bb0a0d54c80-a22fbe2c-1bb5-49cc-b194-25c0f2b870f4"; - } else if fw_info.starts_with("B-FIRU") | fw_info.starts_with("B-FIRH") | fw_info.starts_with("B-FIRBSP") | fw_info.starts_with("B-FIR2"){ - secret = "SHWJUH:db48ad51-c784-4f06-af57-1070a910c536-6a028bb5-e83e-45da-b326-a3a39ccba26c"; - } else if fw_info.starts_with("B-FIRB"){ - secret = "d6442d-7b46b2f4-0f11-4623-af63-8bb0a0d54c80-a22fbe2c-1bb5-49cc-b194-25c0f2b870f4"; - } else if fw_info.starts_with("T-MST10P"){ - secret = "b4c136-fbc93576-b3e8-4035-bf4e-ba4cb4ada1ac-f0d81cc4-8301-4832-bd60-f331295743ba"; - } else if fw_info.starts_with("B-ECB"){ - secret = "SHWJUH:8fb684a9-84c1-46cf-aa81-977bce241542-6db4c136-8540-4ee4-8704-d9cd18590d11"; - } else if fw_info.starts_with("T-VAL"){ - secret = "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00001abc2010"; - } else if fw_info.starts_with("T-TDT"){ - secret = "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00002abc2010"; - } else if fw_info.starts_with("T-MSX"){ - secret = "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00004abc2010"; - } else if fw_info.starts_with("T-CH"){ - secret = "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-611c4f8d4a71"; - } else if fw_info.starts_with("T-ECP") { + let mut secret: Option<&str> = None; + + //find secret + for (prefix, value) in keys::SAMSUNG { + if fw_info.starts_with(prefix) { + secret = Some(value); + break; + } + } + if let Some(p) = secret { + println!("Secret: {}", p); } else { println!("Sorry, this firmware is not supported!"); - return Ok(()); + std::process::exit(1); } for entry in fs::read_dir(image_path)? { @@ -86,6 +73,7 @@ pub fn extract_samsung_old(path: &PathBuf, output_folder: &str) -> Result<(), Bo let filename = path.file_name().unwrap().to_str().unwrap(); let file_size = file.metadata()?.len(); println!("\nFile: {}", filename); + let data = common::read_file(&file, 0, file_size.try_into().unwrap())?; let salt = &data[8..16]; @@ -95,25 +83,31 @@ pub fn extract_samsung_old(path: &PathBuf, output_folder: &str) -> Result<(), Bo //Old -> key: md5 of (sha1 of secret as TEXT + salt) // iv: md5 of (md5 of key + key) - //2012 -> key: md5 of (secret + salt) + //2012 -> key: md5 of (secret(as bytes) + salt) // iv: md5 of (md5 of key + key) + if fw_info.starts_with("T-ECP") { - let key: Vec = [&secret_t_ecp, salt].concat(); + let mut key = Vec::new(); + key.extend_from_slice(&decode(secret.unwrap())?); + key.extend_from_slice(salt); key_md5 = md5::compute(&key); let mut iv = Vec::new(); iv.extend_from_slice(&key_md5.0); iv.extend_from_slice(&key); iv_md5 = md5::compute(&iv); + } else { let mut hasher = Sha1::new(); - hasher.update(secret); + hasher.update(secret.as_ref().unwrap()); let secret_digest = hasher.finalize(); // yes it needs to be a string first then into bytes let secret_digest_string = format!("{:x}", secret_digest); let secret_digest_bytes = secret_digest_string.as_bytes(); - let key: Vec = [&secret_digest_bytes, salt].concat(); + let mut key = Vec::new(); + key.extend_from_slice(&secret_digest_bytes); + key.extend_from_slice(salt); key_md5 = md5::compute(&key); let mut iv = Vec::new(); @@ -124,7 +118,6 @@ pub fn extract_samsung_old(path: &PathBuf, output_folder: &str) -> Result<(), Bo //println!("Key: {:02x?}", key_md5); //println!("IV: {:02x?}", iv_md5); - let end = file_size - 260; println!("- Decrypting file..."); let decrypted_data = decrypt_aes(&data[16..end.try_into().unwrap()], &key_md5, &iv_md5)?; diff --git a/src/keys.rs b/src/keys.rs new file mode 100644 index 0000000..a0c4229 --- /dev/null +++ b/src/keys.rs @@ -0,0 +1,60 @@ +//samsung old keys +pub static SAMSUNG: &[(&str, &str)] = &[ + ("T-GA", "SHWJUH:85a045ae-2296-484c-b457-ede832fcfbe1-646390a3-105e-40aa-85f6-da3086c70111"), + ("T-MST5", "SHWJUH:eceb2c14-db11-425e-9ebf-5f9607f0eb4b-3c38193e-751e-4719-8884-9e76322c0cec"), + ("T-MST10P","b4c136-fbc93576-b3e8-4035-bf4e-ba4cb4ada1ac-f0d81cc4-8301-4832-bd60-f331295743ba"), + ("T-VAL", "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00001abc2010"), + ("T-TDT", "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00002abc2010"), + ("T-MSX", "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-00004abc2010"), + ("T-CH", "A435HX:d3e90afc-0f09-4054-9bac-350cc8dfc901-7cee72ea-15ae-45ce-b0f5-611c4f8d4a71"), + ("T-ECP", "3EF6067262CF0C678598BFF22169D1F1EA57C284"), +]; + +//pfl upg keys +pub static PFLUPG: &[(&str, &str)] = &[ + ("q5551", "D7EE8ED11AC048ED225D4F5F53F8509E55C5D94256A703C79E4CA78AE93ECE1639FE466363AD962BD6D6DE0C46FD19F363687C1D8A21820740A6E7FF87F41C4900DCE1E26EC122E5D4DFA76BFC8F296816B8D0910325E9DC5CBCC9579CF15FC0253EF7CF4919B7613491A5D7BF75DC1888531C458967FD1CF64B33139550BAA5"), + ("qf1eu", "ACD684155C7CCCB04372A8808514489FA9EE75D305987D1337420241FDBE0AE1F7CDFBB931C9D56C91D36F2CE79D222695B484FF42BCA12CE362C7C9ABBDEEC8E5D6107FADCF2D4DA5DF0693E13ACE54A18AEB21C051F6B62C075A1791985547C1CFF4FB5B6EA7E0A9405A1B2BB71EB89A9B209E0F62BF9794D673179C0E60F1"), + ("q591e", "AFAF89062747CBB29343C4E4EA775E4CFDF5FAFCD92C9DD858A8725201BA54AB973BEFEE04EBF3046910FBBC78B10120AE16D80BA734931E97248BC6B1D4A909F087D37BC0A9C2210FF8A2BE44C00F31E4DD8713A364623637FF75EBBCE9D3A840DB67E0FA910F127F679496F6C21112E3E3AD4ACA459FDE1CC58E300682E6F9"), + ("q522e", "C41BE92C212BAC76B48261E2A1704028287DD7E121C11DA25F709E864FBDC1BD8C7F226F57605A4B42D768CDD629AF9E54011A0967AFC2826331406FB1E90321620738526EA0BEA59F1A0E612AE891C396112F13531F423DF02F94D1C871429549F4D5B30D9CA3EFDCC6D7A96849F7C1788DE8FAAEDD36560337008DF06D612F"), + ("q5481", "9E7DA389815251E82A84A1182807702E72A0B0E0FF707C8E73E2EA71F79D5FAAFFC6E0B90ED16E13A4289C78A7D3BDA90626162AAE169D7BE28D6A635585CC10639C4E312E288EB8F7C5A44518B7E8A26A45C5023C5078A972A4CC219CA020BAF524F7429257B7AD76E1B15390879064C6ED59CC1F20CC04EEC26C9CF7FC0727"), + ("q5431", "C5FD937B301A5CEF4B6C25F187728C99636515D058895FEA469496E2B24907FC7721648841F8AE4C618E215673D0C029752FA970B6F9A7F48C9331293D3B1D43E4DFC7B52914973642CD3E4EE0AD11F5254505038F95CACE0DF21FC769B34E134435D88AB617D2981F66EF45BBC7796CFB1086C5D5672E837204991FE53BC1CF"), +]; + +//MSD10 keys +//fw prefix, type, key +pub static MSD10: &[(&str, &str, &str)] = &[ + ("T-NT14M", "old", "95d01e0bae861a05695bc8a6edb2ea835a09accd"), + ("T-HKM", "tizen", "1ac8989ff57db5e75ea67b033050871c"), + ("T-HKP", "tizen", "cce8a3ef92f3e94895999e928f4dd6c3"), +]; + +//MSD11 keys +pub static MSD11: &[(&str, &str)] = &[ + ("T-JZM", "9b1d077c0d137d406c79ddacb6b159fe"), //2015 + ("T-HKMFK", "c7097975e8ab994beb5eaae57e0ba77c"), //2016 + ("T-KTM2L", "46b04f5e794ca4377a20951c9ea00427"), //2018 + ("T-KTM2", "29110e0ce940b3a9b67d3e158f3f1342"), //2018 + ("T-KTM", "d0d49d5f36f5c0da50062fbf32168f5b"), //2017 + ("T-KTSU", "19e1ba41163f03735e692d9daa2cbb47"), //2018 + ("T-KTSD", "39332605ff47a0aea999b10ce9087389"), //2018 + ("T-NKL", "5bab1098dab48792619ebd63650d929f"), //2020 +]; + +//epk2 keys +pub static EPK2: &[(&str, &str)] = &[ + ("214BF3C129547AF31D32A5ECB4742192", "unknown"), + ("1F1E1D1C1B1A19180706050403020100", "BCM35230/early MTK5369 and LG1152"), + ("7184C9C428D03C445188234D5A827196", "mtk5369 - Mediatek GP4"), + ("385A992430196A8C44F1985823C01440", "mtk5398 (a2) - Mediatek NetCast 4/4.5"), + ("6856A0482475A8B41728A35474810203", "new BCM35230"), + ("2F2E2D2C2B2A29281716151413121110", "Saturn7/BCM3556"), + ("212D3B2A5C2D3A2C4D5B234B1A321D2A", "new Saturn7/old LM1"), + ("4F836AAEB4301F26172A9B0E1120EAF4", "LM1 PDP"), + ("4EE662C7A2C0917F7328DE73A0836C6B", "LM1 LCD"), + ("2F534ABE34801A36B7DA6B3EB1C04AD4", "m1 - MStar non-webOS"), + ("7B2CA5943D2E752CF58606228C5B2DAD", "m1a - MStar non-webOS (L15 signage)"), + ("D55C6864035A8C8A2B35A6D6C4565596", "m2 - MStar SimpleSmart"), + ("68A284B4953CAD15024BED2C4F852A09", "lm14 - MStar NetCast 4.5"), + ("4813B5B63C998A2874EF3320684AC8D9", "lg1152 - LX GP4"), + ("14B3623488212250C7C992AACD537447", "lg115x - LX NC4"), +]; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 64cdbb0..6e713bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod common; mod formats; +mod keys; use clap::Parser; use std::path::{PathBuf};