diff --git a/Cargo.lock b/Cargo.lock index f742def..a20bdcc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,6 +517,7 @@ dependencies = [ "regex", "rsa", "sha1", + "thiserror", ] [[package]] @@ -596,6 +597,26 @@ dependencies = [ "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]] name = "typenum" version = "1.18.0" diff --git a/Cargo.toml b/Cargo.toml index 2d38ed6..c933993 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,4 @@ glob = "0" regex = "1" clap = { version = "4", features = ["derive"] } anyhow = "1" +thiserror = "2" diff --git a/src/bin/rustii/title/wad.rs b/src/bin/rustii/title/wad.rs index 239b4f0..424e73a 100644 --- a/src/bin/rustii/title/wad.rs +++ b/src/bin/rustii/title/wad.rs @@ -117,21 +117,21 @@ pub fn convert_wad(input: &str, target: &ConvertTargets, output: &Option Target::Dev => { title.tmd.set_signature_issuer(String::from("Root-CA00000002-CP00000007"))?; 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.tmd.is_vwii = 0; }, Target::Retail => { title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?; 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.tmd.is_vwii = 0; }, Target::Vwii => { title.tmd.set_signature_issuer(String::from("Root-CA00000001-CP00000004"))?; 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.tmd.is_vwii = 1; } diff --git a/src/title/commonkeys.rs b/src/title/commonkeys.rs index 9697c09..c7ccea9 100644 --- a/src/title/commonkeys.rs +++ b/src/title/commonkeys.rs @@ -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 /// 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) -> [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. // The is_dev argument is an option, and if it's set to false or None, then the regular // common key will be used. @@ -18,8 +18,8 @@ pub fn get_common_key(index: u8, is_dev: Option) -> [u8; 16] { 2 => selected_key = VWII_KEY, _ => { match is_dev { - Some(true) => selected_key = DEV_COMMON_KEY, - _ => selected_key = COMMON_KEY, + true => selected_key = DEV_COMMON_KEY, + false => selected_key = COMMON_KEY, } } } @@ -32,22 +32,22 @@ mod tests { #[test] 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] 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] 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] 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] 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]); } } diff --git a/src/title/crypto.rs b/src/title/crypto.rs index 2e0befc..58d9625 100644 --- a/src/title/crypto.rs +++ b/src/title/crypto.rs @@ -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. -pub fn decrypt_title_key(title_key_enc: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: Option) -> [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); type Aes128CbcDec = cbc::Decryptor; 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. -pub fn encrypt_title_key(title_key_dec: [u8; 16], common_key_index: u8, title_id: [u8; 8], is_dev: Option) -> [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); type Aes128CbcEnc = cbc::Encryptor; let encryptor = Aes128CbcEnc::new(&get_common_key(common_key_index, is_dev).into(), &iv.into()); diff --git a/src/title/ticket.rs b/src/title/ticket.rs index dea23ea..0e5fe93 100644 --- a/src/title/ticket.rs +++ b/src/title/ticket.rs @@ -185,7 +185,7 @@ impl Ticket { pub fn dec_title_key(&self) -> [u8; 16] { // Get the dev status of this Ticket so decrypt_title_key knows the right common key. 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).