Make is_dev for get_common_key() non-optional

This commit is contained in:
Campbell 2025-04-03 13:41:44 -04:00
parent 405df67e49
commit 0bda6dabf3
Signed by: NinjaCheetah
GPG Key ID: 39C2500E1778B156
6 changed files with 36 additions and 14 deletions

21
Cargo.lock generated
View File

@ -517,6 +517,7 @@ dependencies = [
"regex", "regex",
"rsa", "rsa",
"sha1", "sha1",
"thiserror",
] ]
[[package]] [[package]]
@ -596,6 +597,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.18.0" version = "1.18.0"

View File

@ -34,3 +34,4 @@ glob = "0"
regex = "1" regex = "1"
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
anyhow = "1" anyhow = "1"
thiserror = "2"

View File

@ -117,21 +117,21 @@ pub fn convert_wad(input: &str, target: &ConvertTargets, output: &Option<String>
Target::Dev => { Target::Dev => {
title.tmd.set_signature_issuer(String::from("Root-CA00000002-CP00000007"))?; title.tmd.set_signature_issuer(String::from("Root-CA00000002-CP00000007"))?;
title.ticket.set_signature_issuer(String::from("Root-CA00000002-XS00000006"))?; title.ticket.set_signature_issuer(String::from("Root-CA00000002-XS00000006"))?;
title_key_new = crypto::encrypt_title_key(title_key, 0, title.ticket.title_id, Some(true)); title_key_new = crypto::encrypt_title_key(title_key, 0, title.ticket.title_id, true);
title.ticket.common_key_index = 0; title.ticket.common_key_index = 0;
title.tmd.is_vwii = 0; title.tmd.is_vwii = 0;
}, },
Target::Retail => { Target::Retail => {
title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?; title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?;
title.ticket.set_signature_issuer(String::from("Root-CA00000001-XS00000003"))?; title.ticket.set_signature_issuer(String::from("Root-CA00000001-XS00000003"))?;
title_key_new = crypto::encrypt_title_key(title_key, 0, title.ticket.title_id, Some(false)); title_key_new = crypto::encrypt_title_key(title_key, 0, title.ticket.title_id, false);
title.ticket.common_key_index = 0; title.ticket.common_key_index = 0;
title.tmd.is_vwii = 0; title.tmd.is_vwii = 0;
}, },
Target::Vwii => { Target::Vwii => {
title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?; title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?;
title.ticket.set_signature_issuer(String::from("Root-CA00000001-XS00000003"))?; title.ticket.set_signature_issuer(String::from("Root-CA00000001-XS00000003"))?;
title_key_new = crypto::encrypt_title_key(title_key, 2, title.ticket.title_id, Some(false)); title_key_new = crypto::encrypt_title_key(title_key, 2, title.ticket.title_id, false);
title.ticket.common_key_index = 2; title.ticket.common_key_index = 2;
title.tmd.is_vwii = 1; title.tmd.is_vwii = 1;
} }

View File

@ -8,7 +8,7 @@ const DEV_COMMON_KEY: &str = "a1604a6a7123b529ae8bec32c816fcaa";
/// Returns the common key for the specified index. Providing Some(true) for the optional argument /// Returns the common key for the specified index. Providing Some(true) for the optional argument
/// is_dev will make index 0 return the development common key instead of the retail common key. /// is_dev will make index 0 return the development common key instead of the retail common key.
pub fn get_common_key(index: u8, is_dev: Option<bool>) -> [u8; 16] { pub fn get_common_key(index: u8, is_dev: bool) -> [u8; 16] {
// Match the Korean and vWii keys, and if they don't match then fall back on the common key. // Match the Korean and vWii keys, and if they don't match then fall back on the common key.
// The is_dev argument is an option, and if it's set to false or None, then the regular // The is_dev argument is an option, and if it's set to false or None, then the regular
// common key will be used. // common key will be used.
@ -18,8 +18,8 @@ pub fn get_common_key(index: u8, is_dev: Option<bool>) -> [u8; 16] {
2 => selected_key = VWII_KEY, 2 => selected_key = VWII_KEY,
_ => { _ => {
match is_dev { match is_dev {
Some(true) => selected_key = DEV_COMMON_KEY, true => selected_key = DEV_COMMON_KEY,
_ => selected_key = COMMON_KEY, false => selected_key = COMMON_KEY,
} }
} }
} }
@ -32,22 +32,22 @@ mod tests {
#[test] #[test]
fn test_get_common_key() { fn test_get_common_key() {
assert_eq!(get_common_key(0, None), [0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7]); assert_eq!(get_common_key(0, false), [0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7]);
} }
#[test] #[test]
fn test_get_invalid_index() { fn test_get_invalid_index() {
assert_eq!(get_common_key(57, None), [0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7]); assert_eq!(get_common_key(57, false), [0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7]);
} }
#[test] #[test]
fn test_get_korean_key() { fn test_get_korean_key() {
assert_eq!(get_common_key(1, None), [0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e, 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e]); assert_eq!(get_common_key(1, false), [0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e, 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e]);
} }
#[test] #[test]
fn test_get_vwii_key() { fn test_get_vwii_key() {
assert_eq!(get_common_key(2, None), [0x30, 0xbf, 0xc7, 0x6e, 0x7c, 0x19, 0xaf, 0xbb, 0x23, 0x16, 0x33, 0x30, 0xce, 0xd7, 0xc2, 0x8d]); assert_eq!(get_common_key(2, false), [0x30, 0xbf, 0xc7, 0x6e, 0x7c, 0x19, 0xaf, 0xbb, 0x23, 0x16, 0x33, 0x30, 0xce, 0xd7, 0xc2, 0x8d]);
} }
#[test] #[test]
fn test_get_dev_key() { fn test_get_dev_key() {
assert_eq!(get_common_key(0, Some(true)), [0xa1, 0x60, 0x4a, 0x6a, 0x71, 0x23, 0xb5, 0x29, 0xae, 0x8b, 0xec, 0x32, 0xc8, 0x16, 0xfc, 0xaa]); assert_eq!(get_common_key(0, true), [0xa1, 0x60, 0x4a, 0x6a, 0x71, 0x23, 0xb5, 0x29, 0xae, 0x8b, 0xec, 0x32, 0xc8, 0x16, 0xfc, 0xaa]);
} }
} }

View File

@ -15,7 +15,7 @@ fn title_id_to_iv(title_id: [u8; 8]) -> [u8; 16] {
} }
/// Decrypts a Title Key using the specified common key and the corresponding Title ID. /// Decrypts a Title Key using the specified common key and the corresponding Title ID.
pub fn decrypt_title_key(title_key_enc: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: Option<bool>) -> [u8; 16] { pub fn decrypt_title_key(title_key_enc: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: bool) -> [u8; 16] {
let iv = title_id_to_iv(title_id); let iv = title_id_to_iv(title_id);
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>; type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
let decryptor = Aes128CbcDec::new(&get_common_key(common_key_index, is_dev).into(), &iv.into()); let decryptor = Aes128CbcDec::new(&get_common_key(common_key_index, is_dev).into(), &iv.into());
@ -25,7 +25,7 @@ pub fn decrypt_title_key(title_key_enc: [u8; 16], common_key_index: u8, title_id
} }
/// Encrypts a Title Key using the specified common key and the corresponding Title ID. /// Encrypts a Title Key using the specified common key and the corresponding Title ID.
pub fn encrypt_title_key(title_key_dec: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: Option<bool>) -> [u8; 16] { pub fn encrypt_title_key(title_key_dec: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: bool) -> [u8; 16] {
let iv = title_id_to_iv(title_id); let iv = title_id_to_iv(title_id);
type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>; type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>;
let encryptor = Aes128CbcEnc::new(&get_common_key(common_key_index, is_dev).into(), &iv.into()); let encryptor = Aes128CbcEnc::new(&get_common_key(common_key_index, is_dev).into(), &iv.into());

View File

@ -185,7 +185,7 @@ impl Ticket {
pub fn dec_title_key(&self) -> [u8; 16] { pub fn dec_title_key(&self) -> [u8; 16] {
// Get the dev status of this Ticket so decrypt_title_key knows the right common key. // Get the dev status of this Ticket so decrypt_title_key knows the right common key.
let is_dev = self.is_dev(); let is_dev = self.is_dev();
decrypt_title_key(self.title_key, self.common_key_index, self.title_id, Some(is_dev)) decrypt_title_key(self.title_key, self.common_key_index, self.title_id, is_dev)
} }
/// Gets whether a Ticket was signed for development (true) or retail (false). /// Gets whether a Ticket was signed for development (true) or retail (false).