diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb7de4a..659a77b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,32 +42,30 @@ jobs: command: test args: --all-features ${{ matrix.target }} - # TODO: Run FMT. - #fmt: - # name: Rustfmt - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v2 - # - uses: actions-rs/toolchain@v1 - # with: - # profile: minimal - # - run: rustup component add rustfmt - # - uses: actions-rs/cargo@v1 - # with: - # command: fmt - # args: --all -- --check + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: rustfmt + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check - # TODO: Run clippy. - #clippy: - # name: Clippy - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v2 - # - uses: actions-rs/toolchain@v1 - # with: - # profile: minimal - # - run: rustup component add clippy - # - uses: actions-rs/cargo@v1 - # with: - # command: clippy - # args: --all-features -- -D warnings \ No newline at end of file + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: clippy + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-features -- -D warnings \ No newline at end of file diff --git a/src/bin/cargo-nro.rs b/src/bin/cargo-nro.rs index d9fa9f2..adc802b 100644 --- a/src/bin/cargo-nro.rs +++ b/src/bin/cargo-nro.rs @@ -1,37 +1,37 @@ #[macro_use] extern crate clap; -extern crate url; extern crate linkle; extern crate serde; extern crate serde_json; +extern crate url; #[macro_use] extern crate serde_derive; extern crate cargo_metadata; extern crate goblin; extern crate scroll; +use scroll::IOwrite; use std::env::{self, VarError}; -use std::process::{Command, Stdio}; -use std::path::{Path, PathBuf}; use std::fs::File; -use std::io::{Write, Read}; -use scroll::IOwrite; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; -use linkle::format::{romfs::RomFs, nxo::NxoFile, nacp::NacpFile}; -use cargo_metadata::{Package, Message}; -use clap::{Arg, App}; -use url::Url; -use goblin::elf::{Elf, Header as ElfHeader, ProgramHeader}; -use goblin::elf::section_header::{SHT_NOBITS, SHT_SYMTAB, SHT_STRTAB}; -use failure::Fail; +use cargo_metadata::{Message, Package}; +use clap::{App, Arg}; use derive_more::Display; +use failure::Fail; +use goblin::elf::section_header::{SHT_NOBITS, SHT_STRTAB, SHT_SYMTAB}; +use goblin::elf::{Elf, Header as ElfHeader, ProgramHeader}; +use linkle::format::{nacp::NacpFile, nxo::NxoFile, romfs::RomFs}; +use url::Url; #[derive(Debug, Fail, Display)] enum Error { #[display(fmt = "{}", _0)] Goblin(#[cause] goblin::error::Error), #[display(fmt = "{}", _0)] - Linkle(#[cause] linkle::error::Error) + Linkle(#[cause] linkle::error::Error), } impl From for Error { @@ -95,19 +95,38 @@ const CARGO_OPTIONS: &str = "CARGO OPTIONS: -Z ... Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details -h, --help Prints help information"; - -fn get_metadata(manifest_path: &Path, package_id: &str, target_name: &str) -> (Package, PackageMetadata) { +fn get_metadata( + manifest_path: &Path, + package_id: &str, + target_name: &str, +) -> (Package, PackageMetadata) { let metadata = cargo_metadata::metadata(Some(&manifest_path)).unwrap(); - let package = metadata.packages.into_iter().find(|v| v.id == package_id).unwrap(); - let package_metadata = serde_json::from_value(package.metadata.pointer(&format!("linkle/{}", target_name)).cloned().unwrap_or(serde_json::Value::Null)).unwrap_or_default(); + let package = metadata + .packages + .into_iter() + .find(|v| v.id == package_id) + .unwrap(); + let package_metadata = serde_json::from_value( + package + .metadata + .pointer(&format!("linkle/{}", target_name)) + .cloned() + .unwrap_or(serde_json::Value::Null), + ) + .unwrap_or_default(); (package, package_metadata) } trait BetterIOWrite: IOwrite { - fn iowrite_with_try + scroll::ctx::TryIntoCtx>(&mut self, n: N, ctx: Ctx) - -> Result<(), N::Error> + fn iowrite_with_try< + N: scroll::ctx::SizeWith + scroll::ctx::TryIntoCtx, + >( + &mut self, + n: N, + ctx: Ctx, + ) -> Result<(), N::Error> where - N::Error: From + N::Error: From, { let mut buf = [0u8; 256]; let size = N::size_with(&ctx); @@ -120,7 +139,10 @@ trait BetterIOWrite: IOwrite { impl + ?Sized> BetterIOWrite for W {} -fn generate_debuginfo_romfs>(elf_path: &Path, romfs: Option

) -> Result { +fn generate_debuginfo_romfs>( + elf_path: &Path, + romfs: Option

, +) -> Result { let mut elf_file = File::open(elf_path)?; let mut buffer = Vec::new(); elf_file.read_to_end(&mut buffer)?; @@ -139,12 +161,23 @@ fn generate_debuginfo_romfs>(elf_path: &Path, romfs: Option

) - } = elf; let ctx = goblin::container::Ctx { - container: if is_64 { goblin::container::Container::Big } else { goblin::container::Container::Little }, - le: if little_endian { goblin::container::Endian::Little } else { goblin::container::Endian::Big } + container: if is_64 { + goblin::container::Container::Big + } else { + goblin::container::Container::Little + }, + le: if little_endian { + goblin::container::Endian::Little + } else { + goblin::container::Endian::Big + }, }; for section in section_headers.iter_mut() { - if section.sh_type == SHT_NOBITS || section.sh_type == SHT_SYMTAB || section.sh_type == SHT_STRTAB { + if section.sh_type == SHT_NOBITS + || section.sh_type == SHT_SYMTAB + || section.sh_type == SHT_STRTAB + { continue; } if let Some(Ok(s)) = elf.shdr_strtab.get(section.sh_name) { @@ -156,13 +189,17 @@ fn generate_debuginfo_romfs>(elf_path: &Path, romfs: Option

) - // Calculate section data length + elf/program headers let data_off = ElfHeader::size(&ctx) + ProgramHeader::size(&ctx) * program_headers.len(); - let shoff = data_off as u64 + section_headers.iter().map(|v| { - if v.sh_type != SHT_NOBITS { - v.sh_size - } else { - 0 - } - }).sum::(); + let shoff = data_off as u64 + + section_headers + .iter() + .map(|v| { + if v.sh_type != SHT_NOBITS { + v.sh_size + } else { + 0 + } + }) + .sum::(); // Write ELF header // TODO: Anything else? @@ -177,8 +214,13 @@ fn generate_debuginfo_romfs>(elf_path: &Path, romfs: Option

) - // Write section data let mut cur_idx = data_off; - for section in section_headers.iter_mut().filter(|v| v.sh_type != SHT_NOBITS) { - file.write_all(&buffer[section.sh_offset as usize..(section.sh_offset + section.sh_size) as usize])?; + for section in section_headers + .iter_mut() + .filter(|v| v.sh_type != SHT_NOBITS) + { + file.write_all( + &buffer[section.sh_offset as usize..(section.sh_offset + section.sh_size) as usize], + )?; section.sh_offset = cur_idx as u64; cur_idx += section.sh_size as usize; } @@ -208,7 +250,7 @@ struct PackageMetadata { romfs: Option, nacp: Option, icon: Option, - title_id: Option + title_id: Option, } fn main() { @@ -221,25 +263,32 @@ fn main() { let matches = App::new(crate_name!()) .about("Compile rust switch homebrews with ease!") - .arg(Arg::with_name("CARGO_OPTIONS") - .raw(true) - .help("Options that will be passed to cargo build")) + .arg( + Arg::with_name("CARGO_OPTIONS") + .raw(true) + .help("Options that will be passed to cargo build"), + ) .after_help(CARGO_OPTIONS) .get_matches_from(args); - let rust_target_path = match env::var("RUST_TARGET_PATH") { Err(VarError::NotPresent) => { // TODO: Handle workspace - find_project_root(&env::current_dir().unwrap()).unwrap().into() - }, + find_project_root(&env::current_dir().unwrap()) + .unwrap() + .into() + } s => PathBuf::from(s.unwrap()), }; let mut command = Command::new("xargo"); command - .args(&["build", "--target=aarch64-roblabla-switch", "--message-format=json"]) + .args(&[ + "build", + "--target=aarch64-roblabla-switch", + "--message-format=json", + ]) .stdout(Stdio::piped()) .env("RUST_TARGET_PATH", rust_target_path.as_os_str()); @@ -252,7 +301,10 @@ fn main() { let iter = cargo_metadata::parse_message_stream(command.stdout.unwrap()); for message in iter { match message { - Ok(Message::CompilerArtifact(ref artifact)) if artifact.target.kind.contains(&"bin".into()) || artifact.target.kind.contains(&"cdylib".into()) => { + Ok(Message::CompilerArtifact(ref artifact)) + if artifact.target.kind.contains(&"bin".into()) + || artifact.target.kind.contains(&"cdylib".into()) => + { // Find the artifact's source. This is not going to be pretty. // For whatever reason, cargo thought it'd be a *great idea* to make file URLs use // the non-standard "path+file:///" scheme, instead of, y'know, the ""file:///" everyone @@ -273,7 +325,8 @@ fn main() { let root = url.to_file_path().unwrap(); let manifest = root.join("Cargo.toml"); - let (package, target_metadata) = get_metadata(&manifest, &artifact.package_id.raw, &artifact.target.name); + let (package, target_metadata) = + get_metadata(&manifest, &artifact.package_id.raw, &artifact.target.name); let romfs = if let Some(romfs) = target_metadata.romfs { let romfs_path = root.join(romfs); @@ -312,30 +365,34 @@ fn main() { nacp.title_id = target_metadata.title_id; } - let romfs = generate_debuginfo_romfs(Path::new(&artifact.filenames[0]), romfs).unwrap(); + let romfs = + generate_debuginfo_romfs(Path::new(&artifact.filenames[0]), romfs).unwrap(); let mut new_name = PathBuf::from(artifact.filenames[0].clone()); assert!(new_name.set_extension("nro")); - NxoFile::from_elf(&artifact.filenames[0]).unwrap() - .write_nro(&mut File::create(new_name.clone()).unwrap(), - Some(romfs), - icon_file, - Some(nacp) - ).unwrap(); + NxoFile::from_elf(&artifact.filenames[0]) + .unwrap() + .write_nro( + &mut File::create(new_name.clone()).unwrap(), + Some(romfs), + icon_file, + Some(nacp), + ) + .unwrap(); println!("Built {}", new_name.to_string_lossy()); - }, + } Ok(Message::CompilerArtifact(_artifact)) => { //println!("{:#?}", artifact); - }, + } Ok(Message::CompilerMessage(msg)) => { if let Some(msg) = msg.message.rendered { println!("{}", msg); } else { println!("{:?}", msg); } - }, + } Ok(_) => (), Err(err) => { panic!("{:?}", err); diff --git a/src/bin/linkle_clap.rs b/src/bin/linkle_clap.rs index ca0f669..944dec9 100644 --- a/src/bin/linkle_clap.rs +++ b/src/bin/linkle_clap.rs @@ -2,11 +2,11 @@ extern crate structopt; extern crate linkle; -use std::fs::{OpenOptions, File}; +use linkle::error::ResultExt; +use std::fs::{File, OpenOptions}; use std::path::{Path, PathBuf}; use std::process; use structopt::StructOpt; -use linkle::error::ResultExt; #[derive(StructOpt)] #[structopt(name = "linkle", about = "The legendary hero")] @@ -72,7 +72,7 @@ enum Opt { /// Sets the input file to use. input_file: String, /// Sets the output file to use. - output_file: String + output_file: String, }, /// Create a RomFS file from a directory. #[structopt(name = "romfs")] @@ -94,48 +94,82 @@ enum Opt { /// Key file to use #[structopt(parse(from_os_str), short = "k", long = "keyset")] keyfile: Option, - } + }, } -fn create_nxo(format: &str, input_file: &str, output_file: &str, icon_file: Option<&str>, romfs_dir: Option<&str>, nacp_file: Option<&str>) -> Result<(), linkle::error::Error> { +fn create_nxo( + format: &str, + input_file: &str, + output_file: &str, + icon_file: Option<&str>, + romfs_dir: Option<&str>, + nacp_file: Option<&str>, +) -> Result<(), linkle::error::Error> { let romfs_dir = if let Some(romfs_path) = romfs_dir { - Some(linkle::format::romfs::RomFs::from_directory(Path::new(&romfs_path))?) + Some(linkle::format::romfs::RomFs::from_directory(Path::new( + &romfs_path, + ))?) } else { None }; let nacp_file = if let Some(nacp_path) = nacp_file { - Some(linkle::format::nacp::NacpFile::from_file(&nacp_path).map_err(|err| (err, &nacp_path))?) + Some( + linkle::format::nacp::NacpFile::from_file(&nacp_path) + .map_err(|err| (err, &nacp_path))?, + ) } else { None }; - let mut nxo = linkle::format::nxo::NxoFile::from_elf(&input_file).map_err(|err| (err, &input_file))?; + let mut nxo = + linkle::format::nxo::NxoFile::from_elf(&input_file).map_err(|err| (err, &input_file))?; let mut option = OpenOptions::new(); let output_option = option.write(true).create(true).truncate(true); match format { "nro" => { - let mut out_file = output_option.open(output_file).map_err(|err| (err, output_file))?; - nxo.write_nro(&mut out_file, romfs_dir, icon_file.as_ref().map(|v| &**v), nacp_file) + let mut out_file = output_option + .open(output_file) .map_err(|err| (err, output_file))?; - }, + nxo.write_nro( + &mut out_file, + romfs_dir, + icon_file.as_ref().map(|v| &**v), + nacp_file, + ) + .map_err(|err| (err, output_file))?; + } "nso" => { - let mut out_file = output_option.open(output_file).map_err(|err| (err, output_file))?; - nxo.write_nso(&mut out_file).map_err(|err| (err, output_file))?; + let mut out_file = output_option + .open(output_file) + .map_err(|err| (err, output_file))?; + nxo.write_nso(&mut out_file) + .map_err(|err| (err, output_file))?; } _ => process::exit(1), } Ok(()) } -fn create_kip(input_file: &str, npdm_file: &str, output_file: &str) -> Result<(), linkle::error::Error> { - let mut nxo = linkle::format::nxo::NxoFile::from_elf(&input_file).map_err(|err| (err, &input_file))?; +fn create_kip( + input_file: &str, + npdm_file: &str, + output_file: &str, +) -> Result<(), linkle::error::Error> { + let mut nxo = + linkle::format::nxo::NxoFile::from_elf(&input_file).map_err(|err| (err, &input_file))?; let npdm = serde_json::from_reader(File::open(npdm_file).map_err(|err| (err, npdm_file))?)?; let mut option = OpenOptions::new(); let output_option = option.write(true).create(true).truncate(true); output_option.open(output_file)?; - nxo.write_kip1(&mut output_option.open(output_file).map_err(|err| (err, output_file))?, &npdm).map_err(|err| (err, output_file))?; + nxo.write_kip1( + &mut output_option + .open(output_file) + .map_err(|err| (err, output_file))?, + &npdm, + ) + .map_err(|err| (err, output_file))?; Ok(()) } @@ -143,7 +177,12 @@ fn create_pfs0(input_directory: &str, output_file: &str) -> Result<(), linkle::e let mut pfs0 = linkle::format::pfs0::Pfs0::from_directory(&input_directory)?; let mut option = OpenOptions::new(); let output_option = option.write(true).create(true).truncate(true); - pfs0.write_pfs0(&mut output_option.open(output_file).map_err(|err| (err, output_file))?).map_err(|err| (err, output_file))?; + pfs0.write_pfs0( + &mut output_option + .open(output_file) + .map_err(|err| (err, output_file))?, + ) + .map_err(|err| (err, output_file))?; Ok(()) } @@ -156,7 +195,7 @@ fn extract_pfs0(input_path: &str, output_directory: &str) -> Result<(), linkle:: match std::fs::create_dir(path) { Ok(()) => (), Err(ref err) if err.kind() == std::io::ErrorKind::AlreadyExists => (), - Err(err) => Err((err, path))? + Err(err) => return Err((err, path).into()), } for file in pfs0.files() { let mut file = file?; @@ -172,8 +211,11 @@ fn create_nacp(input_file: &str, output_file: &str) -> Result<(), linkle::error: let mut nacp = linkle::format::nacp::NacpFile::from_file(&input_file)?; let mut option = OpenOptions::new(); let output_option = option.write(true).create(true).truncate(true); - let mut out_file = output_option.open(output_file).map_err(|err| (err, output_file))?; - nacp.write(&mut out_file).map_err(|err| (err, output_file))?; + let mut out_file = output_option + .open(output_file) + .map_err(|err| (err, output_file))?; + nacp.write(&mut out_file) + .map_err(|err| (err, output_file))?; Ok(()) } @@ -181,8 +223,12 @@ fn create_romfs(input_directory: &Path, output_file: &Path) -> Result<(), linkle let romfs = linkle::format::romfs::RomFs::from_directory(&input_directory)?; let mut option = OpenOptions::new(); let output_option = option.write(true).create(true).truncate(true); - let mut out_file = output_option.open(output_file).map_err(|err| (err, output_file))?; - romfs.write(&mut out_file).map_err(|err| (err, output_file))?; + let mut out_file = output_option + .open(output_file) + .map_err(|err| (err, output_file))?; + romfs + .write(&mut out_file) + .map_err(|err| (err, output_file))?; Ok(()) } @@ -203,13 +249,45 @@ fn to_opt_ref>(s: &Option) -> Option<&U> { fn process_args(app: &Opt) { let res = match app { - Opt::Nro { ref input_file, ref output_file, ref icon, ref romfs, ref nacp } => create_nxo("nro", input_file, output_file, to_opt_ref(icon), to_opt_ref(romfs), to_opt_ref(nacp)), - Opt::Nso { ref input_file, ref output_file } => create_nxo("nso", input_file, output_file, None, None, None), - Opt::Kip { ref input_file, ref npdm_file, ref output_file } => create_kip(input_file, npdm_file, output_file), - Opt::Pfs0 { ref input_directory, ref output_file } => create_pfs0(input_directory, output_file), - Opt::Pfs0Extract { ref input_file, ref output_directory } => extract_pfs0(input_file, output_directory), - Opt::Nacp { ref input_file, ref output_file } => create_nacp(input_file, output_file), - Opt::Romfs { ref input_directory, ref output_file } => create_romfs(input_directory, output_file), + Opt::Nro { + ref input_file, + ref output_file, + ref icon, + ref romfs, + ref nacp, + } => create_nxo( + "nro", + input_file, + output_file, + to_opt_ref(icon), + to_opt_ref(romfs), + to_opt_ref(nacp), + ), + Opt::Nso { + ref input_file, + ref output_file, + } => create_nxo("nso", input_file, output_file, None, None, None), + Opt::Kip { + ref input_file, + ref npdm_file, + ref output_file, + } => create_kip(input_file, npdm_file, output_file), + Opt::Pfs0 { + ref input_directory, + ref output_file, + } => create_pfs0(input_directory, output_file), + Opt::Pfs0Extract { + ref input_file, + ref output_directory, + } => extract_pfs0(input_file, output_directory), + Opt::Nacp { + ref input_file, + ref output_file, + } => create_nacp(input_file, output_file), + Opt::Romfs { + ref input_directory, + ref output_file, + } => create_romfs(input_directory, output_file), Opt::Keygen { dev, ref keyfile } => print_keys(*dev, to_opt_ref(keyfile)), }; diff --git a/src/error.rs b/src/error.rs index 9e2195e..ac037d0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,12 +1,12 @@ +use block_modes::BlockModeError; +use derive_more::Display; +use failure::Backtrace; +use failure::Fail; +use ini; use std::io; +use std::path::{Path, PathBuf}; use std::str::Utf8Error; use std::string::FromUtf8Error; -use std::path::{Path, PathBuf}; -use ini; -use failure::Backtrace; -use block_modes::BlockModeError; -use failure::Fail; -use derive_more::Display; #[derive(Debug, Fail, Display)] pub enum Error { @@ -14,7 +14,10 @@ pub enum Error { Deserialization(#[cause] serde_json::error::Error), #[display(fmt = "{}: {}", "_1.display()", _0)] Io(#[cause] io::Error, PathBuf, Backtrace), - #[display(fmt = "Internal IO Error (please submit a bug report with the backtrace): {}", _0)] + #[display( + fmt = "Internal IO Error (please submit a bug report with the backtrace): {}", + _0 + )] IoInternal(#[cause] io::Error, Backtrace), #[display(fmt = "Decryption failed")] BlockMode(BlockModeError, Backtrace), @@ -87,7 +90,11 @@ impl From for Error { impl From for Error { fn from(err: FromUtf8Error) -> Error { // Why the heck does OsStr not have display()? - Error::Utf8Conversion(String::from_utf8_lossy(err.as_bytes()).into_owned(), err.utf8_error(), Backtrace::new()) + Error::Utf8Conversion( + String::from_utf8_lossy(err.as_bytes()).into_owned(), + err.utf8_error(), + Backtrace::new(), + ) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index e921d5c..97d597e 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -1,6 +1,6 @@ pub mod nacp; +mod npdm; pub mod nxo; pub mod pfs0; pub mod romfs; -mod npdm; mod utils; diff --git a/src/format/nacp.rs b/src/format/nacp.rs index 9632293..09ce831 100644 --- a/src/format/nacp.rs +++ b/src/format/nacp.rs @@ -1,10 +1,10 @@ -use byteorder::{LittleEndian, WriteBytesExt}; use crate::format::utils; +use byteorder::{LittleEndian, WriteBytesExt}; +use serde_derive::{Deserialize, Serialize}; +use serde_json; use std; use std::fs::File; use std::io::Write; -use serde_derive::{Serialize, Deserialize}; -use serde_json; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct NacpLangEntry { @@ -99,7 +99,10 @@ impl NacpFile { .clone() .unwrap_or_else(|| "Unknown Application".to_string()); let mut version = self.version.clone().unwrap_or_else(|| "1.0.0".to_string()); - let mut author = self.author.clone().unwrap_or_else(|| "Unknown Author".to_string()); + let mut author = self + .author + .clone() + .unwrap_or_else(|| "Unknown Author".to_string()); let title_id = match &self.title_id { None => 0, diff --git a/src/format/npdm.rs b/src/format/npdm.rs index f301a7d..6561efd 100644 --- a/src/format/npdm.rs +++ b/src/format/npdm.rs @@ -1,14 +1,7 @@ -use byteorder::{LittleEndian, WriteBytesExt}; -use crate::format::utils; -use std; -use std::fmt; -use std::fs::File; -use std::io::Write; -use std::collections::HashMap; use crate::format::utils::HexOrNum; -use serde_derive::{Serialize, Deserialize}; -use serde_json; use bit_field::BitField; +use serde_derive::{Deserialize, Serialize}; +use std::collections::HashMap; use std::convert::TryFrom; #[derive(Serialize, Deserialize, Debug)] @@ -47,21 +40,20 @@ impl KernelCapability { lowest_thread_priority, highest_cpu_id, lowest_cpu_id, - } => { - vec![*0b111u32 - .set_bits(04..10, u32::from(*lowest_thread_priority)) - .set_bits(10..16, u32::from(*highest_thread_priority)) - .set_bits(16..24, u32::from(*lowest_cpu_id)) - .set_bits(24..32, u32::from(*highest_cpu_id))] - }, + } => vec![*0b111u32 + .set_bits(4..10, u32::from(*lowest_thread_priority)) + .set_bits(10..16, u32::from(*highest_thread_priority)) + .set_bits(16..24, u32::from(*lowest_cpu_id)) + .set_bits(24..32, u32::from(*highest_cpu_id))], KernelCapability::Syscalls(syscalls) => { let mut masks = vec![0b1111u32; 6]; let mut used = [false; 6]; for (idx, mask) in masks.iter_mut().enumerate() { mask.set_bits(29..32, idx as u32); } - for (syscall_name, syscall_val) in syscalls { - masks[syscall_val.0 as usize / 24].set_bit(usize::try_from((syscall_val.0 % 24) + 5).unwrap(), true); + for syscall_val in syscalls.values() { + masks[syscall_val.0 as usize / 24] + .set_bit(usize::try_from((syscall_val.0 % 24) + 5).unwrap(), true); used[syscall_val.0 as usize / 24] = true; } for (idx, used) in used.iter().enumerate().rev() { @@ -70,14 +62,14 @@ impl KernelCapability { } } masks - }, + } KernelCapability::Map { address, size, is_ro, is_io, } => { - let mut val = vec![0b111111u32, 0b111111u32]; + let mut val = vec![0b11_1111u32, 0b11_1111u32]; val[0] .set_bits(7..31, u32::try_from(address.0).unwrap()) .set_bit(31, *is_ro); @@ -85,36 +77,28 @@ impl KernelCapability { .set_bits(7..31, u32::try_from(size.0).unwrap()) .set_bit(31, *is_io); val - }, + } KernelCapability::MapPage(page) => { - vec![*0b1111111u32 - .set_bits(8..32, u32::try_from(page.0).unwrap())] - }, - KernelCapability::IrqPair(irq_pair) => { - vec![*0b11111111111u32 - .set_bits(12..22, u32::from(irq_pair[0])) - .set_bits(22..32, u32::from(irq_pair[1]))] - }, + vec![*0b111_1111u32.set_bits(8..32, u32::try_from(page.0).unwrap())] + } + KernelCapability::IrqPair(irq_pair) => vec![*0b111_1111_1111u32 + .set_bits(12..22, u32::from(irq_pair[0])) + .set_bits(22..32, u32::from(irq_pair[1]))], KernelCapability::ApplicationType(app_type) => { - vec![*0b1111111111111u32 - .set_bits(14..17, u32::from(*app_type))] - }, + vec![*0b1_1111_1111_1111u32.set_bits(14..17, u32::from(*app_type))] + } KernelCapability::MinKernelVersion(min_kernel) => { - vec![*0b11111111111111u32 - .set_bits(15..32, u32::try_from(min_kernel.0).unwrap())] - }, + vec![*0b11_1111_1111_1111u32.set_bits(15..32, u32::try_from(min_kernel.0).unwrap())] + } KernelCapability::HandleTableSize(handle_table_size) => { - vec![*0b111111111111111u32 - .set_bits(16..26, u32::from(*handle_table_size))] - }, + vec![*0b111_1111_1111_1111u32.set_bits(16..26, u32::from(*handle_table_size))] + } KernelCapability::DebugFlags { allow_debug, force_debug, - } => { - vec![*0b1111111111111111u32 - .set_bit(17, *allow_debug) - .set_bit(18, *force_debug)] - }, + } => vec![*0b1111_1111_1111_1111u32 + .set_bit(17, *allow_debug) + .set_bit(18, *force_debug)], } } } diff --git a/src/format/nxo.rs b/src/format/nxo.rs index 323d8d1..8066cc4 100644 --- a/src/format/nxo.rs +++ b/src/format/nxo.rs @@ -1,15 +1,15 @@ +use crate::format::utils::HexOrNum; +use crate::format::{nacp::NacpFile, npdm::KernelCapability, romfs::RomFs, utils}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use elf; -use elf::types::{EM_ARM, EM_AARCH64, ProgramHeader, PT_LOAD, SHT_NOTE, Machine, SectionHeader}; -use crate::format::{utils, romfs::RomFs, nacp::NacpFile, npdm::KernelCapability}; +use elf::types::{Machine, ProgramHeader, SectionHeader, EM_AARCH64, EM_ARM, PT_LOAD, SHT_NOTE}; +use serde_derive::{Deserialize, Serialize}; use std; +use std::convert::{TryFrom, TryInto}; use std::fs::File; use std::io::{self, Cursor, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; use std::process; -use serde_derive::{Serialize, Deserialize}; -use crate::format::utils::HexOrNum; -use std::convert::{TryFrom, TryInto}; // TODO: Support switchbrew's embedded files for NRO pub struct NxoFile { @@ -72,25 +72,42 @@ where Ok(()) } -fn write_mod0(nxo_file: &NxoFile, offset: u32, output_writter: &mut T, bss_addr: u32, bss_size: u32) -> std::io::Result<()> +fn write_mod0( + nxo_file: &NxoFile, + offset: u32, + output_writter: &mut T, + bss_addr: u32, + bss_size: u32, +) -> std::io::Result<()> where T: Write, { // MOD magic output_writter.write_all(b"MOD0")?; // Dynamic Offset - output_writter.write_u32::(nxo_file.dynamic_section.as_ref().map(|v| v.addr as u32 - offset).unwrap_or(0))?; + output_writter.write_u32::( + nxo_file + .dynamic_section + .as_ref() + .map(|v| v.addr as u32 - offset) + .unwrap_or(0), + )?; // BSS Start Offset output_writter.write_u32::(bss_addr - offset)?; // BSS End Offset output_writter.write_u32::(bss_addr + bss_size - offset)?; - let (eh_frame_hdr_addr, eh_frame_hdr_size) = nxo_file.eh_frame_hdr_section.as_ref().map(|v| (v.addr, v.size)).unwrap_or((0, 0)); + let (eh_frame_hdr_addr, eh_frame_hdr_size) = nxo_file + .eh_frame_hdr_section + .as_ref() + .map(|v| (v.addr, v.size)) + .unwrap_or((0, 0)); // EH Frame Header Start output_writter.write_u32::(eh_frame_hdr_addr as u32 - offset)?; // EH Frame Header End - output_writter.write_u32::(eh_frame_hdr_addr as u32 + eh_frame_hdr_size as u32 - offset)?; + output_writter + .write_u32::(eh_frame_hdr_addr as u32 + eh_frame_hdr_size as u32 - offset)?; // RTLD ptr - written at runtime by RTLD output_writter.write_u32::(0)?; @@ -161,7 +178,7 @@ impl NxoFile { ".dynstr" => dynstr_section = Some(section.shdr.clone()), ".dynsym" => dynsym_section = Some(section.shdr.clone()), ".eh_frame_hdr" => eh_frame_hdr_section = Some(section.shdr.clone()), - _ => () + _ => (), } } @@ -176,11 +193,17 @@ impl NxoFile { dynamic_section, dynstr_section, dynsym_section, - eh_frame_hdr_section + eh_frame_hdr_section, }) } - pub fn write_nro(&mut self, output_writter: &mut T, romfs: Option, icon: Option<&str>, nacp: Option) -> std::io::Result<()> + pub fn write_nro( + &mut self, + output_writter: &mut T, + romfs: Option, + icon: Option<&str>, + nacp: Option, + ) -> std::io::Result<()> where T: Write, { @@ -253,7 +276,10 @@ impl NxoFile { } output_writter .write_u32::(((segment.memsz + 0xFFF) & !0xFFF) as u32)?; - (segment.vaddr as u32, ((segment.memsz + 0xFFF) & !0xFFF) as u32) + ( + segment.vaddr as u32, + ((segment.memsz + 0xFFF) & !0xFFF) as u32, + ) } _ => { // in this case the bss is missing or is embedeed in .data. libnx does that, let's support it @@ -264,7 +290,10 @@ impl NxoFile { 0 }; output_writter.write_u32::(bss_size)?; - (data_segment.vaddr as u32 + data_segment.memsz as u32, bss_size) + ( + data_segment.vaddr as u32 + data_segment.memsz as u32, + bss_size, + ) } }; @@ -282,43 +311,90 @@ impl NxoFile { output_writter.write_u64::(0)?; // .dynstr section info - output_writter.write_u32::(self.dynstr_section.as_ref().map(|v| u32::try_from(v.addr).unwrap()).unwrap_or(0))?; - output_writter.write_u32::(self.dynstr_section.as_ref().map(|v| u32::try_from(v.size).unwrap()).unwrap_or(0))?; + output_writter.write_u32::( + self.dynstr_section + .as_ref() + .map(|v| u32::try_from(v.addr).unwrap()) + .unwrap_or(0), + )?; + output_writter.write_u32::( + self.dynstr_section + .as_ref() + .map(|v| u32::try_from(v.size).unwrap()) + .unwrap_or(0), + )?; // .dynsym section info - output_writter.write_u32::(self.dynsym_section.as_ref().map(|v| u32::try_from(v.addr).unwrap()).unwrap_or(0))?; - output_writter.write_u32::(self.dynsym_section.as_ref().map(|v| u32::try_from(v.size).unwrap()).unwrap_or(0))?; + output_writter.write_u32::( + self.dynsym_section + .as_ref() + .map(|v| u32::try_from(v.addr).unwrap()) + .unwrap_or(0), + )?; + output_writter.write_u32::( + self.dynsym_section + .as_ref() + .map(|v| u32::try_from(v.size).unwrap()) + .unwrap_or(0), + )?; let module_offset = u32::from_le_bytes(code[4..8].try_into().unwrap()) as usize; - if module_offset != 0 && !( - (0x80..code_size).contains(&(module_offset as u32)) || - (rodata_offset..data_offset).contains(&(module_offset as u32)) || - (data_offset..file_offset).contains(&(module_offset as u32))) + if module_offset != 0 + && !((0x80..code_size).contains(&(module_offset as u32)) + || (rodata_offset..data_offset).contains(&(module_offset as u32)) + || (data_offset..file_offset).contains(&(module_offset as u32))) { panic!("Invalid module offset {}", module_offset) } - if (0x80..code_size).contains(&(module_offset as u32)) && &code[module_offset..module_offset + 4] != b"MOD0" { + if (0x80..code_size).contains(&(module_offset as u32)) + && &code[module_offset..module_offset + 4] != b"MOD0" + { output_writter.write_all(&code[0x80..module_offset])?; - write_mod0(self, module_offset as u32, output_writter, bss_start, bss_size)?; + write_mod0( + self, + module_offset as u32, + output_writter, + bss_start, + bss_size, + )?; output_writter.write_all(&code[module_offset + 0x1C..])?; } else { output_writter.write_all(&code[0x80..])?; } - if (rodata_offset..data_offset).contains(&(module_offset as u32)) && &rodata[module_offset - rodata_offset as usize..module_offset - rodata_offset as usize+ 4] != b"MOD0" { + if (rodata_offset..data_offset).contains(&(module_offset as u32)) + && &rodata + [module_offset - rodata_offset as usize..module_offset - rodata_offset as usize + 4] + != b"MOD0" + { let rodata_module_offset = module_offset - rodata_offset as usize; output_writter.write_all(&rodata[..rodata_module_offset])?; - write_mod0(self, module_offset as u32, output_writter, bss_start, bss_size)?; + write_mod0( + self, + module_offset as u32, + output_writter, + bss_start, + bss_size, + )?; output_writter.write_all(&rodata[rodata_module_offset + 0x1C..])?; } else { output_writter.write_all(&rodata)?; } - if (data_offset..file_offset).contains(&(module_offset as u32)) && &data[module_offset - data_offset as usize..module_offset - data_offset as usize + 4] != b"MOD0" { + if (data_offset..file_offset).contains(&(module_offset as u32)) + && &data[module_offset - data_offset as usize..module_offset - data_offset as usize + 4] + != b"MOD0" + { let data_module_offset = module_offset - data_offset as usize; output_writter.write_all(&data[..data_module_offset])?; - write_mod0(self, module_offset as u32, output_writter, bss_start, bss_size)?; + write_mod0( + self, + module_offset as u32, + output_writter, + bss_start, + bss_size, + )?; output_writter.write_all(&data[data_module_offset + 0x1C..])?; } else { output_writter.write_all(&data)?; @@ -326,7 +402,7 @@ impl NxoFile { // Early return if there's no need for an ASET segment. if let (None, None, None) = (&icon, &romfs, &nacp) { - return Ok(()) + return Ok(()); } // Aset handling @@ -372,7 +448,11 @@ impl NxoFile { }; if let Some(icon) = icon { - assert_eq!(io::copy(&mut File::open(icon)?, output_writter)?, icon_len, "Icon changed while building."); + assert_eq!( + io::copy(&mut File::open(icon)?, output_writter)?, + icon_len, + "Icon changed while building." + ); } if let Some(mut nacp) = nacp { @@ -491,11 +571,31 @@ impl NxoFile { // TODO: SegmentHeaderRelative for .api_info output_writter.write_u64::(0)?; // SegmentHeaderRelative for .dynstr - output_writter.write_u32::(self.dynstr_section.as_ref().map(|v| u32::try_from(v.addr).unwrap()).unwrap_or(0))?; - output_writter.write_u32::(self.dynstr_section.as_ref().map(|v| u32::try_from(v.size).unwrap()).unwrap_or(0))?; + output_writter.write_u32::( + self.dynstr_section + .as_ref() + .map(|v| u32::try_from(v.addr).unwrap()) + .unwrap_or(0), + )?; + output_writter.write_u32::( + self.dynstr_section + .as_ref() + .map(|v| u32::try_from(v.size).unwrap()) + .unwrap_or(0), + )?; // SegmentHeaderRelative for .dynsym - output_writter.write_u32::(self.dynsym_section.as_ref().map(|v| u32::try_from(v.addr).unwrap()).unwrap_or(0))?; - output_writter.write_u32::(self.dynsym_section.as_ref().map(|v| u32::try_from(v.size).unwrap()).unwrap_or(0))?; + output_writter.write_u32::( + self.dynsym_section + .as_ref() + .map(|v| u32::try_from(v.addr).unwrap()) + .unwrap_or(0), + )?; + output_writter.write_u32::( + self.dynsym_section + .as_ref() + .map(|v| u32::try_from(v.size).unwrap()) + .unwrap_or(0), + )?; // .text sha256 let text_sum = utils::calculate_sha256(&code)?; @@ -521,7 +621,7 @@ impl NxoFile { T: Write, { output_writer.write_all(b"KIP1")?; - let mut name : Vec = npdm.name.clone().into(); + let mut name: Vec = npdm.name.clone().into(); name.resize(12, 0); output_writer.write_all(&name[..])?; output_writer.write_u64::(npdm.title_id.0)?; // TitleId @@ -533,10 +633,10 @@ impl NxoFile { output_writer.write_u8(flags)?; } else if self.machine == EM_AARCH64 { // Compression enable, Is64Bit, IsAddrSpace32Bit, UseSystemPoolPartition - output_writer.write_u8(0b00111111)?; + output_writer.write_u8(0b0011_1111)?; } else if self.machine == EM_ARM { // Compression enable, UseSystemPoolPartition - output_writer.write_u8(0b00100111)?; + output_writer.write_u8(0b0010_0111)?; } else { unimplemented!("Unknown machine type"); } @@ -549,12 +649,22 @@ impl NxoFile { let data_data = utils::compress_blz(&mut segment_data).unwrap(); write_kip_segment_header(output_writer, &self.text_segment, 0, text_data.len() as u32)?; - write_kip_segment_header(output_writer, &self.rodata_segment, u32::try_from(npdm.main_thread_stack_size.0).expect("Exected main_thread_stack_size to be an u32"), rodata_data.len() as u32)?; + write_kip_segment_header( + output_writer, + &self.rodata_segment, + u32::try_from(npdm.main_thread_stack_size.0) + .expect("Exected main_thread_stack_size to be an u32"), + rodata_data.len() as u32, + )?; write_kip_segment_header(output_writer, &self.data_segment, 0, data_data.len() as u32)?; if let Some(segment) = self.bss_segment { - output_writer.write_u32::(u32::try_from(segment.vaddr).expect("BSS vaddr too big"))?; - output_writer.write_u32::(u32::try_from(segment.memsz).expect("BSS memsize too big"))?; + output_writer.write_u32::( + u32::try_from(segment.vaddr).expect("BSS vaddr too big"), + )?; + output_writer.write_u32::( + u32::try_from(segment.memsz).expect("BSS memsize too big"), + )?; } else { // in this case the bss is missing or is embedeed in .data. libnx does that, let's support it let data_segment_size = (self.data_segment.filesz + 0xFFF) & !0xFFF; @@ -563,14 +673,16 @@ impl NxoFile { } else { 0 }; - output_writer.write_u32::(u32::try_from(self.data_segment.vaddr + data_segment_size).unwrap())?; + output_writer.write_u32::( + u32::try_from(self.data_segment.vaddr + data_segment_size).unwrap(), + )?; output_writer.write_u32::(bss_size)?; } output_writer.write_u32::(0)?; output_writer.write_u32::(0)?; // Empty Sections: - for i in 4..6 { + for _ in 4..6 { output_writer.write_u32::(0)?; output_writer.write_u32::(0)?; output_writer.write_u32::(0)?; @@ -578,16 +690,24 @@ impl NxoFile { } // Kernel caps: - let caps = npdm.kernel_capabilities.iter() + let caps = npdm + .kernel_capabilities + .iter() .map(|v| v.encode()) .flatten() .collect::>(); - assert!(caps.len() < 0x20, "kernel_capabilities should have less than 0x20 entries!"); + assert!( + caps.len() < 0x20, + "kernel_capabilities should have less than 0x20 entries!" + ); unsafe { // Safety: This is safe. I'm just casting a slice of u32 to a slice of u8 // for fuck's sake. - output_writer.write_all(std::slice::from_raw_parts(caps.as_ptr() as *const u8, caps.len() * 4))?; + output_writer.write_all(std::slice::from_raw_parts( + caps.as_ptr() as *const u8, + caps.len() * 4, + ))?; } output_writer.write_all(&vec![0xFF; (0x20 - caps.len()) * 4])?; @@ -601,13 +721,22 @@ impl NxoFile { } } -pub fn write_kip_segment_header(output_writer: &mut T, segment: &ProgramHeader, attributes: u32, compressed_size: u32) -> std::io::Result<()> +pub fn write_kip_segment_header( + output_writer: &mut T, + segment: &ProgramHeader, + attributes: u32, + compressed_size: u32, +) -> std::io::Result<()> where T: Write, { - output_writer.write_u32::(u32::try_from(segment.vaddr).expect("vaddr too big"))?; - output_writer.write_u32::(u32::try_from(segment.filesz).expect("memsz too big"))?; - output_writer.write_u32::(u32::try_from(compressed_size).expect("Compressed size too big"))?; + output_writer + .write_u32::(u32::try_from(segment.vaddr).expect("vaddr too big"))?; + output_writer + .write_u32::(u32::try_from(segment.filesz).expect("memsz too big"))?; + output_writer.write_u32::( + u32::try_from(compressed_size).expect("Compressed size too big"), + )?; output_writer.write_u32::(attributes)?; Ok(()) diff --git a/src/format/pfs0.rs b/src/format/pfs0.rs index e018e44..466c7b3 100644 --- a/src/format/pfs0.rs +++ b/src/format/pfs0.rs @@ -1,11 +1,11 @@ -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use crate::format::utils; use crate::error::Error; -use crate::utils::{ReadRange, TryClone, align_up}; +use crate::format::utils; +use crate::utils::{align_up, ReadRange, TryClone}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use failure::Backtrace; use std; use std::fs::File; -use std::io::{self, Read, Seek, SeekFrom, Write, BufRead}; +use std::io::{self, BufRead, Read, Seek, SeekFrom, Write}; use std::path::PathBuf; pub trait ReadSeek: Read + Seek {} @@ -15,10 +15,10 @@ impl ReadSeek for T {} enum Pfs0Meta { HostPath(PathBuf), SubFile { - file: Box, + file: Box, name: String, - size: u64 - } + size: u64, + }, } impl Pfs0Meta { @@ -56,7 +56,7 @@ impl Pfs0 { let mut magic = [0; 4]; f.read_exact(&mut magic)?; if &magic != b"PFS0" { - return Err(Error::InvalidPfs0("magic is wrong", Backtrace::new())) + return Err(Error::InvalidPfs0("magic is wrong", Backtrace::new())); } let filecount = f.read_u32::()?; @@ -67,7 +67,7 @@ impl Pfs0 { let string_table_offset = 0x10 + filecount as u64 * 0x18; let data_offset = string_table_offset + string_table_size as u64; - for file in 0..filecount { + for _ in 0..filecount { let offset = data_offset + f.read_u64::()?; let size = f.read_u64::()?; let filename_offset = string_table_offset + f.read_u32::()? as u64; @@ -85,12 +85,10 @@ impl Pfs0 { finalfiles.push(Pfs0Meta::SubFile { file: Box::new(ReadRange::new(f.get_ref().try_clone()?, offset, size)), name: filename, - size + size, }); } - Ok(Pfs0 { - files: finalfiles - }) + Ok(Pfs0 { files: finalfiles }) } pub fn write_pfs0(&mut self, output_writter: &mut T) -> std::io::Result<()> @@ -104,13 +102,8 @@ impl Pfs0 { // Header output_writter.write_all(b"PFS0")?; output_writter.write_u32::(file_count)?; - let string_table_size = utils::align( - files - .iter() - .map(|x| x.file_name().len() + 1) - .sum(), - 0x1F, - ); + let string_table_size = + utils::align(files.iter().map(|x| x.file_name().len() + 1).sum(), 0x1F); output_writter.write_u32::(string_table_size as u32)?; output_writter.write_u32::(0)?; @@ -127,10 +120,13 @@ impl Pfs0 { let mut string_offset = 0; let mut data_offset = 0; - for (file_index, file) in files.iter_mut().enumerate().map(|(idx, path)| (idx as u64, path)) { + for (file_index, file) in files + .iter_mut() + .enumerate() + .map(|(idx, path)| (idx as u64, path)) + { // Seek and write file name to string table - output_writter - .seek(SeekFrom::Start(string_table_pos + string_offset))?; + output_writter.seek(SeekFrom::Start(string_table_pos + string_offset))?; println!( "Writing {}... [{}/{}]", @@ -150,25 +146,23 @@ impl Pfs0 { let file_size = host_file.metadata()?.len(); let name = path.file_name().unwrap().to_str().unwrap(); (&mut host_file as &mut dyn ReadSeek, file_size, name) - }, - Pfs0Meta::SubFile { file, name, size, .. } => { - (file as &mut dyn ReadSeek, *size, &**name) } + Pfs0Meta::SubFile { + file, name, size, .. + } => (file as &mut dyn ReadSeek, *size, &**name), }; // Write file entry to the file entry table - output_writter - .seek(SeekFrom::Start(0x10 + (file_index * 0x18)))?; + output_writter.seek(SeekFrom::Start(0x10 + (file_index * 0x18)))?; output_writter.write_u64::(data_offset)?; output_writter.write_u64::(file_size)?; output_writter.write_u64::(string_offset)?; // Write the actual file content - output_writter - .seek(SeekFrom::Start(data_pos + data_offset))?; + output_writter.seek(SeekFrom::Start(data_pos + data_offset))?; - file.seek(SeekFrom::Start(0)); + file.seek(SeekFrom::Start(0))?; let size = io::copy(file, output_writter)?; assert_eq!(size, file_size); @@ -180,15 +174,13 @@ impl Pfs0 { } pub fn files(self) -> impl Iterator> + 'static { - Pfs0FileIterator { - pfs0: self, - } + Pfs0FileIterator { pfs0: self } } } pub struct Pfs0File { name: String, - file: Box + file: Box, } impl Pfs0File { @@ -221,17 +213,11 @@ impl Iterator for Pfs0FileIterator { let name = meta.file_name().into(); let file = match meta { Pfs0Meta::HostPath(path) => { - File::open(path) - .map(|v| Box::new(v) as Box) - }, - Pfs0Meta::SubFile { mut file, .. } => { - file.seek(SeekFrom::Start(0)) - .map(|_| file) + File::open(path).map(|v| Box::new(v) as Box) } + Pfs0Meta::SubFile { mut file, .. } => file.seek(SeekFrom::Start(0)).map(|_| file), }; - Some(file.map(|file| Pfs0File { - name, file - })) + Some(file.map(|file| Pfs0File { name, file })) } else { None } diff --git a/src/format/romfs.rs b/src/format/romfs.rs index 4cc7d0e..76d8f09 100644 --- a/src/format/romfs.rs +++ b/src/format/romfs.rs @@ -1,12 +1,12 @@ -use std::mem; -use std::rc::{Rc, Weak}; -use std::io::{self, Write, Cursor}; -use std::fs::{self, File}; -use std::cell::RefCell; -use std::path::{Path, PathBuf}; -use byteorder::{WriteBytesExt, LE}; use crate::error::Error; +use byteorder::{WriteBytesExt, LE}; use failure::Backtrace; +use std::cell::RefCell; +use std::fs::{self, File}; +use std::io::{self, Cursor, Write}; +use std::mem; +use std::path::{Path, PathBuf}; +use std::rc::{Rc, Weak}; #[derive(Debug)] struct RomFsDirEntCtx { @@ -58,7 +58,7 @@ struct RomFsDirEntryHdr { child: u32, file: u32, hash: u32, - name_size: u32 + name_size: u32, } #[repr(C)] @@ -69,20 +69,25 @@ struct RomFsFileEntryHdr { offset: u64, size: u64, hash: u32, - name_size: u32 + name_size: u32, } impl RomFsDirEntCtx { #[allow(clippy::new_ret_no_self)] fn new(parent: Weak>, path: PathBuf) -> Rc> { - let filename = path.file_name().expect("Path to terminate properly").to_str().expect("Path to contain non-unicode chars").into(); + let filename = path + .file_name() + .expect("Path to terminate properly") + .to_str() + .expect("Path to contain non-unicode chars") + .into(); Rc::new(RefCell::new(RomFsDirEntCtx { system_path: path, name: filename, entry_offset: 0, parent, child: vec![], - file: vec![] + file: vec![], })) } @@ -96,7 +101,7 @@ impl RomFsDirEntCtx { entry_offset: 0, parent: Weak::new(), child: vec![], - file: vec![] + file: vec![], })); let weak = Rc::downgrade(&root); root.borrow_mut().parent = weak; @@ -115,10 +120,14 @@ fn romfs_get_hash_table_count(mut num_entries: usize) -> usize { } else if num_entries < 19 { num_entries | 1 } else { - while num_entries % 2 == 0 || num_entries % 3 == 0 || - num_entries % 5 == 0 || num_entries % 7 == 0 || - num_entries % 11 == 0 || num_entries % 13 == 0 || - num_entries % 17 == 0 { + while num_entries % 2 == 0 + || num_entries % 3 == 0 + || num_entries % 5 == 0 + || num_entries % 7 == 0 + || num_entries % 11 == 0 + || num_entries % 13 == 0 + || num_entries % 17 == 0 + { num_entries += 1; } num_entries @@ -179,15 +188,24 @@ impl RomFs { })); self.files.push(file_to_add.clone()); parent.borrow_mut().file.push(file_to_add.clone()); - parent.borrow_mut().file.sort_by_key(|v| v.borrow().name.clone()); + parent + .borrow_mut() + .file + .sort_by_key(|v| v.borrow().name.clone()); - self.file_table_size += mem::size_of::() as u64 + align64(file_to_add.borrow().name.len() as u64, 4); + self.file_table_size += mem::size_of::() as u64 + + align64(file_to_add.borrow().name.len() as u64, 4); } else { // Handling a parent component. Find the directory, create if it doesn't exist. if component == "" { continue; } - let new_parent = if let Some(child) = parent.borrow().child.iter().find(|v| v.borrow().name == component) { + let new_parent = if let Some(child) = parent + .borrow() + .child + .iter() + .find(|v| v.borrow().name == component) + { child.clone() } else { // system_path is not used outside from_directory. It's okay if it doesn't @@ -198,13 +216,17 @@ impl RomFs { entry_offset: 0, parent: Rc::downgrade(&parent), child: vec![], - file: vec![] + file: vec![], })); self.dirs.push(child.clone()); parent.borrow_mut().child.push(child.clone()); - parent.borrow_mut().child.sort_by_key(|v| v.borrow().name.clone()); + parent + .borrow_mut() + .child + .sort_by_key(|v| v.borrow().name.clone()); - self.dir_table_size += mem::size_of::() as u64 + align64(child.borrow().name.len() as u64, 4); + self.dir_table_size += mem::size_of::() as u64 + + align64(child.borrow().name.len() as u64, 4); child }; parent = new_parent; @@ -272,32 +294,44 @@ impl RomFs { // Update the context. We want to keep track of the number of directories, and // the size of the dir_table. - ctx.dir_table_size += mem::size_of::() as u64 + align64(new_dir.borrow().name.len() as u64, 4); - + ctx.dir_table_size += mem::size_of::() as u64 + + align64(new_dir.borrow().name.len() as u64, 4); } else if file_type.is_file() { let file = Rc::new(RefCell::new(RomFsFileEntCtx { system_path: entry.path(), - name: entry.path().file_name().expect("Path to terminate properly").to_str().expect("Path to contain non-unicode chars").into(), + name: entry + .path() + .file_name() + .expect("Path to terminate properly") + .to_str() + .expect("Path to contain non-unicode chars") + .into(), entry_offset: 0, offset: 0, size: entry.metadata().map_err(|err| (err, entry.path()))?.len(), - parent: Rc::downgrade(&parent_dir) + parent: Rc::downgrade(&parent_dir), })); ctx.files.push(file.clone()); parent_dir.borrow_mut().file.push(file.clone()); - ctx.file_table_size += mem::size_of::() as u64 + align64(file.borrow().name.len() as u64, 4); - + ctx.file_table_size += mem::size_of::() as u64 + + align64(file.borrow().name.len() as u64, 4); } else if file_type.is_symlink() { - Err(Error::RomFsSymlink(entry.path(), Backtrace::new()))?; + return Err(Error::RomFsSymlink(entry.path(), Backtrace::new())); } else { - Err(Error::RomFsFiletype(entry.path(), Backtrace::new()))?; + return Err(Error::RomFsFiletype(entry.path(), Backtrace::new())); } } - parent_dir.borrow_mut().child.sort_by_key(|v| v.borrow().name.clone()); - parent_dir.borrow_mut().file.sort_by_key(|v| v.borrow().name.clone()); + parent_dir + .borrow_mut() + .child + .sort_by_key(|v| v.borrow().name.clone()); + parent_dir + .borrow_mut() + .file + .sort_by_key(|v| v.borrow().name.clone()); } ctx.files.sort_by_key(|v| v.borrow().internal_path()); @@ -309,11 +343,11 @@ impl RomFs { } pub fn len(&self) -> usize { - (align64(ROMFS_FILEPARTITION_OFS + self.file_partition_size, 4) + - romfs_get_hash_table_count(self.dirs.len() * mem::size_of::()) as u64 + - self.dir_table_size + - romfs_get_hash_table_count(self.files.len() * mem::size_of::()) as u64 + - self.file_table_size) as usize + (align64(ROMFS_FILEPARTITION_OFS + self.file_partition_size, 4) + + romfs_get_hash_table_count(self.dirs.len() * mem::size_of::()) as u64 + + self.dir_table_size + + romfs_get_hash_table_count(self.files.len() * mem::size_of::()) as u64 + + self.file_table_size) as usize } fn calculate_offsets(&mut self) { @@ -332,23 +366,26 @@ impl RomFs { // Set the file offset in the file table section. file.borrow_mut().entry_offset = entry_offset; - entry_offset += mem::size_of::() as u32 + align32(file.borrow().name.len() as u32, 4); + entry_offset += mem::size_of::() as u32 + + align32(file.borrow().name.len() as u32, 4); } // Calculate directory offsets. let mut entry_offset = 0; for dir in self.dirs.iter_mut() { dir.borrow_mut().entry_offset = entry_offset; - entry_offset += mem::size_of::() as u32 + align32(dir.borrow().name.len() as u32, 4); + entry_offset += mem::size_of::() as u32 + + align32(dir.borrow().name.len() as u32, 4); } } - pub fn write(&self, to: &mut dyn Write) -> io::Result<()> { const ROMFS_ENTRY_EMPTY: u32 = 0xFF_FF_FF_FF; - let mut dir_hash_table = vec![ROMFS_ENTRY_EMPTY; romfs_get_hash_table_count(self.dirs.len())]; - let mut file_hash_table = vec![ROMFS_ENTRY_EMPTY; romfs_get_hash_table_count(self.files.len())]; + let mut dir_hash_table = + vec![ROMFS_ENTRY_EMPTY; romfs_get_hash_table_count(self.dirs.len())]; + let mut file_hash_table = + vec![ROMFS_ENTRY_EMPTY; romfs_get_hash_table_count(self.files.len())]; let mut dir_table = vec![0u8; self.dir_table_size as usize]; let mut file_table = vec![0u8; self.file_table_size as usize]; @@ -359,7 +396,11 @@ impl RomFs { let file = file.borrow(); let parent = file.parent.upgrade().unwrap(); let parent = parent.borrow(); - let sibling = parent.file.windows(2).find(|window| Rc::ptr_eq(&window[0], orig_file)).map(|window| window[1].borrow().entry_offset); + let sibling = parent + .file + .windows(2) + .find(|window| Rc::ptr_eq(&window[0], orig_file)) + .map(|window| window[1].borrow().entry_offset); let hash = calc_path_hash(parent.entry_offset, &file.name); let mut cursor = Cursor::new(&mut file_table[file.entry_offset as usize..]); @@ -380,14 +421,28 @@ impl RomFs { let dir = dir.borrow(); let parent = dir.parent.upgrade().unwrap(); let parent = parent.borrow(); - let sibling = parent.child.windows(2).find(|window| window[0].borrow().internal_path() == dir.internal_path()).map(|window| window[1].borrow().entry_offset); + let sibling = parent + .child + .windows(2) + .find(|window| window[0].borrow().internal_path() == dir.internal_path()) + .map(|window| window[1].borrow().entry_offset); let hash = calc_path_hash(parent.entry_offset, &dir.name); let mut cursor = Cursor::new(&mut dir_table[dir.entry_offset as usize..]); cursor.write_u32::(parent.entry_offset)?; cursor.write_u32::(sibling.unwrap_or(ROMFS_ENTRY_EMPTY))?; - cursor.write_u32::(dir.child.first().map(|v| v.borrow().entry_offset).unwrap_or(ROMFS_ENTRY_EMPTY))?; - cursor.write_u32::(dir.file.first().map(|v| v.borrow().entry_offset).unwrap_or(ROMFS_ENTRY_EMPTY))?; + cursor.write_u32::( + dir.child + .first() + .map(|v| v.borrow().entry_offset) + .unwrap_or(ROMFS_ENTRY_EMPTY), + )?; + cursor.write_u32::( + dir.file + .first() + .map(|v| v.borrow().entry_offset) + .unwrap_or(ROMFS_ENTRY_EMPTY), + )?; cursor.write_u32::(dir_hash_table[hash as usize % dir_hash_table.len()])?; cursor.write_u32::(dir.name.len() as u32)?; cursor.write_all(dir.name.as_bytes())?; @@ -429,7 +484,10 @@ impl RomFs { to.write_all(&vec![0; (new_cur_ofs - cur_ofs) as usize])?; cur_ofs = new_cur_ofs; - println!("Writing {} to RomFS image...", file.borrow().system_path.to_string_lossy()); + println!( + "Writing {} to RomFS image...", + file.borrow().system_path.to_string_lossy() + ); assert_eq!(file.borrow().offset, cur_ofs - 0x200, "Wrong offset"); let len = io::copy(&mut File::open(&file.borrow().system_path)?, to)?; @@ -443,7 +501,10 @@ impl RomFs { let cur_ofs = new_cur_ofs; // Write dir hash table - assert_eq!(cur_ofs, align64(ROMFS_FILEPARTITION_OFS + self.file_partition_size, 4)); + assert_eq!( + cur_ofs, + align64(ROMFS_FILEPARTITION_OFS + self.file_partition_size, 4) + ); for hash in dir_hash_table { to.write_u32::(hash)?; } diff --git a/src/format/utils.rs b/src/format/utils.rs index acdc791..60d8cbb 100644 --- a/src/format/utils.rs +++ b/src/format/utils.rs @@ -1,12 +1,12 @@ use elf; use lz4; +use serde::de::{Unexpected, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use sha2::{Digest, Sha256}; use std; use std::fmt; use std::fs::File; use std::io::{Read, Seek, SeekFrom}; -use sha2::{Sha256, Digest}; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use serde::de::{Visitor, Unexpected}; pub fn align(size: usize, padding: usize) -> usize { ((size as usize) + padding) & !padding @@ -39,7 +39,8 @@ pub fn compress_lz4(uncompressed_data: &mut Vec) -> std::io::Result> } pub fn compress_blz(uncompressed_data: &mut Vec) -> blz_nx::BlzResult> { - let mut compressed_data = vec![0; blz_nx::get_worst_compression_buffer_size(uncompressed_data.len())]; + let mut compressed_data = + vec![0; blz_nx::get_worst_compression_buffer_size(uncompressed_data.len())]; let res = blz_nx::compress_raw(&mut uncompressed_data[..], &mut compressed_data[..])?; compressed_data.resize(res, 0); Ok(compressed_data) @@ -76,21 +77,23 @@ impl<'de> Deserialize<'de> for HexOrNum { fn visit_u64(self, v: u64) -> Result where - E: serde::de::Error + E: serde::de::Error, { Ok(v) } fn visit_str(self, v: &str) -> Result where - E: serde::de::Error + E: serde::de::Error, { - if (v.starts_with("0x")) { - u64::from_str_radix(&v[2..], 16).map_err(|_| { - E::invalid_value(Unexpected::Str(v), &"a hex-encoded string") - }) + if v.starts_with("0x") { + u64::from_str_radix(&v[2..], 16) + .map_err(|_| E::invalid_value(Unexpected::Str(v), &"a hex-encoded string")) } else { - Err(E::invalid_value(Unexpected::Str(v), &"a hex-encoded string")) + Err(E::invalid_value( + Unexpected::Str(v), + &"a hex-encoded string", + )) } } } diff --git a/src/lib.rs b/src/lib.rs index e3e1991..07c78ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ +pub mod error; pub mod format; pub mod pki; -pub mod error; mod utils; diff --git a/src/pki.rs b/src/pki.rs index de5b1b2..424e011 100644 --- a/src/pki.rs +++ b/src/pki.rs @@ -1,17 +1,17 @@ -use std::fmt; -use ini::{self, ini::Properties}; -use failure::Backtrace; -use std::fs::File; -use std::io::{self, Write, ErrorKind}; -use std::path::Path; use crate::error::Error; -use aes::Aes128; -use cmac::Cmac; -use cmac::crypto_mac::Mac; -use block_modes::{Ctr128, BlockModeIv, BlockMode}; -use block_modes::block_padding::ZeroPadding; use aes::block_cipher_trait::generic_array::GenericArray; use aes::block_cipher_trait::BlockCipher; +use aes::Aes128; +use block_modes::block_padding::ZeroPadding; +use block_modes::{BlockMode, BlockModeIv, Ctr128}; +use cmac::crypto_mac::Mac; +use cmac::Cmac; +use failure::Backtrace; +use ini::{self, ini::Properties}; +use std::fmt; +use std::fs::File; +use std::io::{self, ErrorKind, Write}; +use std::path::Path; struct Aes128Key([u8; 0x10]); struct AesXtsKey([u8; 0x20]); @@ -37,7 +37,7 @@ macro_rules! impl_debug { Ok(()) } } - } + }; } impl_debug!(Aes128Key); @@ -47,11 +47,19 @@ impl_debug!(Keyblob); impl_debug!(Modulus); impl Keyblob { - fn encrypt(&self, key: &Aes128Key, mac_key: &Aes128Key, keyblob_id: usize) -> Result { + fn encrypt( + &self, + key: &Aes128Key, + mac_key: &Aes128Key, + _keyblob_id: usize, + ) -> Result { let mut encrypted_keyblob = [0; 0xB0]; encrypted_keyblob[0x20..].copy_from_slice(&self.0); - let mut crypter = Ctr128::::new_fixkey(GenericArray::from_slice(&key.0), GenericArray::from_slice(&encrypted_keyblob[0x10..0x20])); + let mut crypter = Ctr128::::new_fixkey( + GenericArray::from_slice(&key.0), + GenericArray::from_slice(&encrypted_keyblob[0x10..0x20]), + ); crypter.encrypt_nopad(&mut encrypted_keyblob[0x20..])?; let mut cmac = Cmac::::new_varkey(&mac_key.0[..]).unwrap(); @@ -62,15 +70,24 @@ impl Keyblob { } impl EncryptedKeyblob { - fn decrypt(&self, key: &Aes128Key, mac_key: &Aes128Key, keyblob_id: usize) -> Result { + fn decrypt( + &self, + key: &Aes128Key, + mac_key: &Aes128Key, + keyblob_id: usize, + ) -> Result { let mut keyblob = [0; 0x90]; keyblob.copy_from_slice(&self.0[0x20..]); let mut cmac = Cmac::::new_varkey(&mac_key.0[..]).unwrap(); cmac.input(&self.0[0x10..]); - cmac.verify(&self.0[..0x10]).map_err(|err| (keyblob_id, err))?; + cmac.verify(&self.0[..0x10]) + .map_err(|err| (keyblob_id, err))?; - let mut crypter = Ctr128::::new_fixkey(GenericArray::from_slice(&key.0), GenericArray::from_slice(&self.0[0x10..0x20])); + let mut crypter = Ctr128::::new_fixkey( + GenericArray::from_slice(&key.0), + GenericArray::from_slice(&self.0[0x10..0x20]), + ); crypter.decrypt_nopad(&mut keyblob)?; Ok(Keyblob(keyblob)) @@ -95,7 +112,6 @@ impl Aes128Key { crypter.decrypt_block(GenericArray::from_mut_slice(&mut newkey[0x10..0x20])); Ok(AesXtsKey(newkey)) - } } @@ -103,7 +119,14 @@ fn key_to_aes(keys: &Properties, name: &str, key: &mut [u8]) -> Result Result Result, Error> { +fn key_to_aes_array( + keys: &Properties, + name: &str, + idx: usize, + key: &mut [u8], +) -> Result, Error> { key_to_aes(keys, &format!("{}_{:02x}", name, idx), key) } @@ -186,7 +214,7 @@ macro_rules! make_key_macros_write { if let Some(key) = &$self.$keyname { writeln!($w, "{} = {}", stringify!($keyname), key)?; } - } + }; } macro_rules! single_key_xts { @@ -194,7 +222,7 @@ macro_rules! make_key_macros_write { if let Some(key) = &$self.$keyname { writeln!($w, "{} = {}", stringify!($keyname), key)?; } - } + }; } macro_rules! multi_key { @@ -209,7 +237,7 @@ macro_rules! make_key_macros_write { writeln!($w, "{}_{:02x} = {}", name, idx, key)?; } } - } + }; } macro_rules! multi_keyblob { @@ -224,7 +252,7 @@ macro_rules! make_key_macros_write { writeln!($w, "{}_{:02x} = {}", name, idx, key)?; } } - } + }; } macro_rules! multi_encrypted_keyblob { @@ -239,9 +267,9 @@ macro_rules! make_key_macros_write { writeln!($w, "{}_{:02x} = {}", name, idx, key)?; } } - } + }; } - } + }; } macro_rules! make_key_macros { @@ -249,15 +277,19 @@ macro_rules! make_key_macros { macro_rules! single_key { ($keyname:tt) => { let mut key = [0; 0x10]; - $self.$keyname.or_in(key_to_aes($section, stringify!($keyname), &mut key)?.map(|()| Aes128Key(key))); - } + $self.$keyname.or_in( + key_to_aes($section, stringify!($keyname), &mut key)?.map(|()| Aes128Key(key)), + ); + }; } macro_rules! single_key_xts { ($keyname:tt) => { let mut key = [0; 0x20]; - $self.$keyname.or_in(key_to_aes($section, stringify!($keyname), &mut key)?.map(|()| AesXtsKey(key))); - } + $self.$keyname.or_in( + key_to_aes($section, stringify!($keyname), &mut key)?.map(|()| AesXtsKey(key)), + ); + }; } macro_rules! multi_key { @@ -269,9 +301,11 @@ macro_rules! make_key_macros { if name.bytes().last() == Some(b's') { name.pop(); } - v.or_in(key_to_aes_array($section, &name, idx, &mut key)?.map(|()| Aes128Key(key))); + v.or_in( + key_to_aes_array($section, &name, idx, &mut key)?.map(|()| Aes128Key(key)), + ); } - } + }; } macro_rules! multi_keyblob { @@ -283,9 +317,11 @@ macro_rules! make_key_macros { if name.bytes().last() == Some(b's') { name.pop(); } - v.or_in(key_to_aes_array($section, &name, idx, &mut key)?.map(|()| Keyblob(key))); + v.or_in( + key_to_aes_array($section, &name, idx, &mut key)?.map(|()| Keyblob(key)), + ); } - } + }; } macro_rules! multi_encrypted_keyblob { @@ -297,14 +333,22 @@ macro_rules! make_key_macros { if name.bytes().last() == Some(b's') { name.pop(); } - v.or_in(key_to_aes_array($section, &name, idx, &mut key)?.map(|()| EncryptedKeyblob(key))); + v.or_in( + key_to_aes_array($section, &name, idx, &mut key)? + .map(|()| EncryptedKeyblob(key)), + ); } - } + }; } - } + }; } -fn generate_kek(src: &Aes128Key, master_key: &Aes128Key, kek_seed: &Aes128Key, key_seed: &Aes128Key) -> Result { +fn generate_kek( + src: &Aes128Key, + master_key: &Aes128Key, + kek_seed: &Aes128Key, + key_seed: &Aes128Key, +) -> Result { let kek = master_key.derive_key(&kek_seed.0)?; let src_kek = kek.derive_key(&src.0)?; src_kek.derive_key(&key_seed.0) @@ -312,7 +356,11 @@ fn generate_kek(src: &Aes128Key, master_key: &Aes128Key, kek_seed: &Aes128Key, k impl Keys { #[allow(clippy::new_ret_no_self)] - fn new(key_path: Option<&Path>, default_key_name: &Path, modulus: ([Modulus; 2], [Modulus; 2], Modulus)) -> Result { + fn new( + key_path: Option<&Path>, + default_key_name: &Path, + modulus: ([Modulus; 2], [Modulus; 2], Modulus), + ) -> Result { let (modulus0, modulus1, modulus2) = modulus; let [modulus00, modulus01] = modulus0; let [modulus10, modulus11] = modulus1; @@ -323,13 +371,20 @@ impl Keys { ..Default::default() }; - let paths = if let Some(key_path) = key_path { vec![Some(key_path.into())] } else { vec![ - dirs::config_dir().map(|mut v| { v.push("switch"); v.push(default_key_name); v }), - dirs::home_dir().map(|mut v| { v.push(".switch"); v.push(default_key_name); v }), + dirs::config_dir().map(|mut v| { + v.push("switch"); + v.push(default_key_name); + v + }), + dirs::home_dir().map(|mut v| { + v.push(".switch"); + v.push(default_key_name); + v + }), ] }; @@ -341,7 +396,7 @@ impl Keys { keys.read_from_ini(file)?; succeed = true; break; - }, + } Err(ref err) if err.kind() == ErrorKind::NotFound => (), Err(err) => println!("Failed to open {}: {}", path.display(), err), } @@ -349,7 +404,7 @@ impl Keys { } if !succeed { - Err(io::Error::new(ErrorKind::NotFound, "Keyfile not found."))?; + return Err(io::Error::new(ErrorKind::NotFound, "Keyfile not found.").into()); } keys.derive_keys()?; @@ -357,191 +412,274 @@ impl Keys { } pub fn new_retail(key_path: Option<&Path>) -> Result { - Keys::new(key_path, Path::new("prod.keys"), ( - /* nca_hdr_fixed_key_modulus: */ [Modulus([ - 0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, 0x61, 0x1D, 0x77, 0x2F, - 0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58, - 0x34, 0xB0, 0x05, 0xA3, 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16, - 0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, 0xF6, 0x00, 0x07, 0xB2, - 0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF, - 0xA7, 0x82, 0xB5, 0xCF, 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67, - 0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, 0x8A, 0x68, 0xC9, 0x26, - 0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C, - 0xCE, 0x02, 0x6F, 0x16, 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE, - 0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, 0x43, 0xF3, 0xFC, 0x86, - 0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35, - 0xF2, 0xF6, 0x56, 0x56, 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B, - 0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, 0xFD, 0x13, 0x63, 0x29, - 0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40, - 0x7E, 0x32, 0x8C, 0x27, 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81, - 0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, 0x9D, 0xE4, 0xF4, 0x03 - ]), Modulus([ - 0xAD, 0xE3, 0xE1, 0xFA, 0x04, 0x35, 0xE5, 0xB6, 0xDD, 0x49, 0xEA, 0x89, 0x29, 0xB1, 0xFF, 0xB6, - 0x43, 0xDF, 0xCA, 0x96, 0xA0, 0x4A, 0x13, 0xDF, 0x43, 0xD9, 0x94, 0x97, 0x96, 0x43, 0x65, 0x48, - 0x70, 0x58, 0x33, 0xA2, 0x7D, 0x35, 0x7B, 0x96, 0x74, 0x5E, 0x0B, 0x5C, 0x32, 0x18, 0x14, 0x24, - 0xC2, 0x58, 0xB3, 0x6C, 0x22, 0x7A, 0xA1, 0xB7, 0xCB, 0x90, 0xA7, 0xA3, 0xF9, 0x7D, 0x45, 0x16, - 0xA5, 0xC8, 0xED, 0x8F, 0xAD, 0x39, 0x5E, 0x9E, 0x4B, 0x51, 0x68, 0x7D, 0xF8, 0x0C, 0x35, 0xC6, - 0x3F, 0x91, 0xAE, 0x44, 0xA5, 0x92, 0x30, 0x0D, 0x46, 0xF8, 0x40, 0xFF, 0xD0, 0xFF, 0x06, 0xD2, - 0x1C, 0x7F, 0x96, 0x18, 0xDC, 0xB7, 0x1D, 0x66, 0x3E, 0xD1, 0x73, 0xBC, 0x15, 0x8A, 0x2F, 0x94, - 0xF3, 0x00, 0xC1, 0x83, 0xF1, 0xCD, 0xD7, 0x81, 0x88, 0xAB, 0xDF, 0x8C, 0xEF, 0x97, 0xDD, 0x1B, - 0x17, 0x5F, 0x58, 0xF6, 0x9A, 0xE9, 0xE8, 0xC2, 0x2F, 0x38, 0x15, 0xF5, 0x21, 0x07, 0xF8, 0x37, - 0x90, 0x5D, 0x2E, 0x02, 0x40, 0x24, 0x15, 0x0D, 0x25, 0xB7, 0x26, 0x5D, 0x09, 0xCC, 0x4C, 0xF4, - 0xF2, 0x1B, 0x94, 0x70, 0x5A, 0x9E, 0xEE, 0xED, 0x77, 0x77, 0xD4, 0x51, 0x99, 0xF5, 0xDC, 0x76, - 0x1E, 0xE3, 0x6C, 0x8C, 0xD1, 0x12, 0xD4, 0x57, 0xD1, 0xB6, 0x83, 0xE4, 0xE4, 0xFE, 0xDA, 0xE9, - 0xB4, 0x3B, 0x33, 0xE5, 0x37, 0x8A, 0xDF, 0xB5, 0x7F, 0x89, 0xF1, 0x9B, 0x9E, 0xB0, 0x15, 0xB2, - 0x3A, 0xFE, 0xEA, 0x61, 0x84, 0x5B, 0x7D, 0x4B, 0x23, 0x12, 0x0B, 0x83, 0x12, 0xF2, 0x22, 0x6B, - 0xB9, 0x22, 0x96, 0x4B, 0x26, 0x0B, 0x63, 0x5E, 0x96, 0x57, 0x52, 0xA3, 0x67, 0x64, 0x22, 0xCA, - 0xD0, 0x56, 0x3E, 0x74, 0xB5, 0x98, 0x1F, 0x0D, 0xF8, 0xB3, 0x34, 0xE6, 0x98, 0x68, 0x5A, 0xAD, - ])], - /* acid_fixed_key_modulus: */ [Modulus([ - 0xDD, 0xC8, 0xDD, 0xF2, 0x4E, 0x6D, 0xF0, 0xCA, 0x9E, 0xC7, 0x5D, 0xC7, 0x7B, 0xAD, 0xFE, 0x7D, - 0x23, 0x89, 0x69, 0xB6, 0xF2, 0x06, 0xA2, 0x02, 0x88, 0xE1, 0x55, 0x91, 0xAB, 0xCB, 0x4D, 0x50, - 0x2E, 0xFC, 0x9D, 0x94, 0x76, 0xD6, 0x4C, 0xD8, 0xFF, 0x10, 0xFA, 0x5E, 0x93, 0x0A, 0xB4, 0x57, - 0xAC, 0x51, 0xC7, 0x16, 0x66, 0xF4, 0x1A, 0x54, 0xC2, 0xC5, 0x04, 0x3D, 0x1B, 0xFE, 0x30, 0x20, - 0x8A, 0xAC, 0x6F, 0x6F, 0xF5, 0xC7, 0xB6, 0x68, 0xB8, 0xC9, 0x40, 0x6B, 0x42, 0xAD, 0x11, 0x21, - 0xE7, 0x8B, 0xE9, 0x75, 0x01, 0x86, 0xE4, 0x48, 0x9B, 0x0A, 0x0A, 0xF8, 0x7F, 0xE8, 0x87, 0xF2, - 0x82, 0x01, 0xE6, 0xA3, 0x0F, 0xE4, 0x66, 0xAE, 0x83, 0x3F, 0x4E, 0x9F, 0x5E, 0x01, 0x30, 0xA4, - 0x00, 0xB9, 0x9A, 0xAE, 0x5F, 0x03, 0xCC, 0x18, 0x60, 0xE5, 0xEF, 0x3B, 0x5E, 0x15, 0x16, 0xFE, - 0x1C, 0x82, 0x78, 0xB5, 0x2F, 0x47, 0x7C, 0x06, 0x66, 0x88, 0x5D, 0x35, 0xA2, 0x67, 0x20, 0x10, - 0xE7, 0x6C, 0x43, 0x68, 0xD3, 0xE4, 0x5A, 0x68, 0x2A, 0x5A, 0xE2, 0x6D, 0x73, 0xB0, 0x31, 0x53, - 0x1C, 0x20, 0x09, 0x44, 0xF5, 0x1A, 0x9D, 0x22, 0xBE, 0x12, 0xA1, 0x77, 0x11, 0xE2, 0xA1, 0xCD, - 0x40, 0x9A, 0xA2, 0x8B, 0x60, 0x9B, 0xEF, 0xA0, 0xD3, 0x48, 0x63, 0xA2, 0xF8, 0xA3, 0x2C, 0x08, - 0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, 0x69, 0x2B, 0x31, 0x6A, - 0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA, - 0x37, 0xEA, 0xE8, 0x1E, 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B, - 0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, 0x7D, 0x35, 0x22, 0xFD - ]), Modulus([ - 0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, 0x96, 0x5A, 0xBF, 0x90, - 0xAC, 0xA7, 0xFD, 0x9B, 0x5B, 0xBD, 0x8A, 0x26, 0xB0, 0xCB, 0x20, 0x28, 0x9A, 0x72, 0x12, 0xF5, - 0x20, 0x65, 0xB3, 0xB9, 0x84, 0x58, 0x1F, 0x27, 0xBC, 0x7C, 0xA2, 0xC9, 0x9E, 0x18, 0x95, 0xCF, - 0xC2, 0x73, 0x2E, 0x74, 0x8C, 0x66, 0xE5, 0x9E, 0x79, 0x2B, 0xB8, 0x07, 0x0C, 0xB0, 0x4E, 0x8E, - 0xAB, 0x85, 0x21, 0x42, 0xC4, 0xC5, 0x6D, 0x88, 0x9C, 0xDB, 0x15, 0x95, 0x3F, 0x80, 0xDB, 0x7A, - 0x9A, 0x7D, 0x41, 0x56, 0x25, 0x17, 0x18, 0x42, 0x4D, 0x8C, 0xAC, 0xA5, 0x7B, 0xDB, 0x42, 0x5D, - 0x59, 0x35, 0x45, 0x5D, 0x8A, 0x02, 0xB5, 0x70, 0xC0, 0x72, 0x35, 0x46, 0xD0, 0x1D, 0x60, 0x01, - 0x4A, 0xCC, 0x1C, 0x46, 0xD3, 0xD6, 0x35, 0x52, 0xD6, 0xE1, 0xF8, 0x3B, 0x5D, 0xEA, 0xDD, 0xB8, - 0xFE, 0x7D, 0x50, 0xCB, 0x35, 0x23, 0x67, 0x8B, 0xB6, 0xE4, 0x74, 0xD2, 0x60, 0xFC, 0xFD, 0x43, - 0xBF, 0x91, 0x08, 0x81, 0xC5, 0x4F, 0x5D, 0x16, 0x9A, 0xC4, 0x9A, 0xC6, 0xF6, 0xF3, 0xE1, 0xF6, - 0x5C, 0x07, 0xAA, 0x71, 0x6C, 0x13, 0xA4, 0xB1, 0xB3, 0x66, 0xBF, 0x90, 0x4C, 0x3D, 0xA2, 0xC4, - 0x0B, 0xB8, 0x3D, 0x7A, 0x8C, 0x19, 0xFA, 0xFF, 0x6B, 0xB9, 0x1F, 0x02, 0xCC, 0xB6, 0xD3, 0x0C, - 0x7D, 0x19, 0x1F, 0x47, 0xF9, 0xC7, 0x40, 0x01, 0xFA, 0x46, 0xEA, 0x0B, 0xD4, 0x02, 0xE0, 0x3D, - 0x30, 0x9A, 0x1A, 0x0F, 0xEA, 0xA7, 0x66, 0x55, 0xF7, 0xCB, 0x28, 0xE2, 0xBB, 0x99, 0xE4, 0x83, - 0xC3, 0x43, 0x03, 0xEE, 0xDC, 0x1F, 0x02, 0x23, 0xDD, 0xD1, 0x2D, 0x39, 0xA4, 0x65, 0x75, 0x03, - 0xEF, 0x37, 0x9C, 0x06, 0xD6, 0xFA, 0xA1, 0x15, 0xF0, 0xDB, 0x17, 0x47, 0x26, 0x4F, 0x49, 0x03 - ])], - /* package2_fixed_key_modulus: */ Modulus([ - 0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59, - 0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE, - 0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5, - 0x6C, 0x39, 0x7F, 0x41, 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74, - 0x8B, 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, 0xD3, 0x48, - 0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, 0xBD, 0xC3, 0x29, 0x90, 0xBE, - 0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32, - 0x9A, 0x42, 0x9D, 0x09, 0x8B, 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A, - 0xD7, 0xE1, 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, 0x0B, - 0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, 0x9E, 0xF4, 0x46, 0xA3, - 0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9, - 0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47, - 0xFD, 0xFA, 0x4C, 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D, - 0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, 0x9A, 0x3F, 0xF2, - 0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF, - 0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F - ]) - )) + Keys::new( + key_path, + Path::new("prod.keys"), + ( + /* nca_hdr_fixed_key_modulus: */ + [ + Modulus([ + 0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, + 0x61, 0x1D, 0x77, 0x2F, 0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, + 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58, 0x34, 0xB0, 0x05, 0xA3, + 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16, + 0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, + 0xF6, 0x00, 0x07, 0xB2, 0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, + 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF, 0xA7, 0x82, 0xB5, 0xCF, + 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67, + 0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, + 0x8A, 0x68, 0xC9, 0x26, 0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, + 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C, 0xCE, 0x02, 0x6F, 0x16, + 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE, + 0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, + 0x43, 0xF3, 0xFC, 0x86, 0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, + 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35, 0xF2, 0xF6, 0x56, 0x56, + 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B, + 0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, + 0xFD, 0x13, 0x63, 0x29, 0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, + 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40, 0x7E, 0x32, 0x8C, 0x27, + 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81, + 0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, + 0x9D, 0xE4, 0xF4, 0x03, + ]), + Modulus([ + 0xAD, 0xE3, 0xE1, 0xFA, 0x04, 0x35, 0xE5, 0xB6, 0xDD, 0x49, 0xEA, 0x89, + 0x29, 0xB1, 0xFF, 0xB6, 0x43, 0xDF, 0xCA, 0x96, 0xA0, 0x4A, 0x13, 0xDF, + 0x43, 0xD9, 0x94, 0x97, 0x96, 0x43, 0x65, 0x48, 0x70, 0x58, 0x33, 0xA2, + 0x7D, 0x35, 0x7B, 0x96, 0x74, 0x5E, 0x0B, 0x5C, 0x32, 0x18, 0x14, 0x24, + 0xC2, 0x58, 0xB3, 0x6C, 0x22, 0x7A, 0xA1, 0xB7, 0xCB, 0x90, 0xA7, 0xA3, + 0xF9, 0x7D, 0x45, 0x16, 0xA5, 0xC8, 0xED, 0x8F, 0xAD, 0x39, 0x5E, 0x9E, + 0x4B, 0x51, 0x68, 0x7D, 0xF8, 0x0C, 0x35, 0xC6, 0x3F, 0x91, 0xAE, 0x44, + 0xA5, 0x92, 0x30, 0x0D, 0x46, 0xF8, 0x40, 0xFF, 0xD0, 0xFF, 0x06, 0xD2, + 0x1C, 0x7F, 0x96, 0x18, 0xDC, 0xB7, 0x1D, 0x66, 0x3E, 0xD1, 0x73, 0xBC, + 0x15, 0x8A, 0x2F, 0x94, 0xF3, 0x00, 0xC1, 0x83, 0xF1, 0xCD, 0xD7, 0x81, + 0x88, 0xAB, 0xDF, 0x8C, 0xEF, 0x97, 0xDD, 0x1B, 0x17, 0x5F, 0x58, 0xF6, + 0x9A, 0xE9, 0xE8, 0xC2, 0x2F, 0x38, 0x15, 0xF5, 0x21, 0x07, 0xF8, 0x37, + 0x90, 0x5D, 0x2E, 0x02, 0x40, 0x24, 0x15, 0x0D, 0x25, 0xB7, 0x26, 0x5D, + 0x09, 0xCC, 0x4C, 0xF4, 0xF2, 0x1B, 0x94, 0x70, 0x5A, 0x9E, 0xEE, 0xED, + 0x77, 0x77, 0xD4, 0x51, 0x99, 0xF5, 0xDC, 0x76, 0x1E, 0xE3, 0x6C, 0x8C, + 0xD1, 0x12, 0xD4, 0x57, 0xD1, 0xB6, 0x83, 0xE4, 0xE4, 0xFE, 0xDA, 0xE9, + 0xB4, 0x3B, 0x33, 0xE5, 0x37, 0x8A, 0xDF, 0xB5, 0x7F, 0x89, 0xF1, 0x9B, + 0x9E, 0xB0, 0x15, 0xB2, 0x3A, 0xFE, 0xEA, 0x61, 0x84, 0x5B, 0x7D, 0x4B, + 0x23, 0x12, 0x0B, 0x83, 0x12, 0xF2, 0x22, 0x6B, 0xB9, 0x22, 0x96, 0x4B, + 0x26, 0x0B, 0x63, 0x5E, 0x96, 0x57, 0x52, 0xA3, 0x67, 0x64, 0x22, 0xCA, + 0xD0, 0x56, 0x3E, 0x74, 0xB5, 0x98, 0x1F, 0x0D, 0xF8, 0xB3, 0x34, 0xE6, + 0x98, 0x68, 0x5A, 0xAD, + ]), + ], + /* acid_fixed_key_modulus: */ + [ + Modulus([ + 0xDD, 0xC8, 0xDD, 0xF2, 0x4E, 0x6D, 0xF0, 0xCA, 0x9E, 0xC7, 0x5D, 0xC7, + 0x7B, 0xAD, 0xFE, 0x7D, 0x23, 0x89, 0x69, 0xB6, 0xF2, 0x06, 0xA2, 0x02, + 0x88, 0xE1, 0x55, 0x91, 0xAB, 0xCB, 0x4D, 0x50, 0x2E, 0xFC, 0x9D, 0x94, + 0x76, 0xD6, 0x4C, 0xD8, 0xFF, 0x10, 0xFA, 0x5E, 0x93, 0x0A, 0xB4, 0x57, + 0xAC, 0x51, 0xC7, 0x16, 0x66, 0xF4, 0x1A, 0x54, 0xC2, 0xC5, 0x04, 0x3D, + 0x1B, 0xFE, 0x30, 0x20, 0x8A, 0xAC, 0x6F, 0x6F, 0xF5, 0xC7, 0xB6, 0x68, + 0xB8, 0xC9, 0x40, 0x6B, 0x42, 0xAD, 0x11, 0x21, 0xE7, 0x8B, 0xE9, 0x75, + 0x01, 0x86, 0xE4, 0x48, 0x9B, 0x0A, 0x0A, 0xF8, 0x7F, 0xE8, 0x87, 0xF2, + 0x82, 0x01, 0xE6, 0xA3, 0x0F, 0xE4, 0x66, 0xAE, 0x83, 0x3F, 0x4E, 0x9F, + 0x5E, 0x01, 0x30, 0xA4, 0x00, 0xB9, 0x9A, 0xAE, 0x5F, 0x03, 0xCC, 0x18, + 0x60, 0xE5, 0xEF, 0x3B, 0x5E, 0x15, 0x16, 0xFE, 0x1C, 0x82, 0x78, 0xB5, + 0x2F, 0x47, 0x7C, 0x06, 0x66, 0x88, 0x5D, 0x35, 0xA2, 0x67, 0x20, 0x10, + 0xE7, 0x6C, 0x43, 0x68, 0xD3, 0xE4, 0x5A, 0x68, 0x2A, 0x5A, 0xE2, 0x6D, + 0x73, 0xB0, 0x31, 0x53, 0x1C, 0x20, 0x09, 0x44, 0xF5, 0x1A, 0x9D, 0x22, + 0xBE, 0x12, 0xA1, 0x77, 0x11, 0xE2, 0xA1, 0xCD, 0x40, 0x9A, 0xA2, 0x8B, + 0x60, 0x9B, 0xEF, 0xA0, 0xD3, 0x48, 0x63, 0xA2, 0xF8, 0xA3, 0x2C, 0x08, + 0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, + 0x69, 0x2B, 0x31, 0x6A, 0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, + 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA, 0x37, 0xEA, 0xE8, 0x1E, + 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B, + 0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, + 0x7D, 0x35, 0x22, 0xFD, + ]), + Modulus([ + 0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, + 0x96, 0x5A, 0xBF, 0x90, 0xAC, 0xA7, 0xFD, 0x9B, 0x5B, 0xBD, 0x8A, 0x26, + 0xB0, 0xCB, 0x20, 0x28, 0x9A, 0x72, 0x12, 0xF5, 0x20, 0x65, 0xB3, 0xB9, + 0x84, 0x58, 0x1F, 0x27, 0xBC, 0x7C, 0xA2, 0xC9, 0x9E, 0x18, 0x95, 0xCF, + 0xC2, 0x73, 0x2E, 0x74, 0x8C, 0x66, 0xE5, 0x9E, 0x79, 0x2B, 0xB8, 0x07, + 0x0C, 0xB0, 0x4E, 0x8E, 0xAB, 0x85, 0x21, 0x42, 0xC4, 0xC5, 0x6D, 0x88, + 0x9C, 0xDB, 0x15, 0x95, 0x3F, 0x80, 0xDB, 0x7A, 0x9A, 0x7D, 0x41, 0x56, + 0x25, 0x17, 0x18, 0x42, 0x4D, 0x8C, 0xAC, 0xA5, 0x7B, 0xDB, 0x42, 0x5D, + 0x59, 0x35, 0x45, 0x5D, 0x8A, 0x02, 0xB5, 0x70, 0xC0, 0x72, 0x35, 0x46, + 0xD0, 0x1D, 0x60, 0x01, 0x4A, 0xCC, 0x1C, 0x46, 0xD3, 0xD6, 0x35, 0x52, + 0xD6, 0xE1, 0xF8, 0x3B, 0x5D, 0xEA, 0xDD, 0xB8, 0xFE, 0x7D, 0x50, 0xCB, + 0x35, 0x23, 0x67, 0x8B, 0xB6, 0xE4, 0x74, 0xD2, 0x60, 0xFC, 0xFD, 0x43, + 0xBF, 0x91, 0x08, 0x81, 0xC5, 0x4F, 0x5D, 0x16, 0x9A, 0xC4, 0x9A, 0xC6, + 0xF6, 0xF3, 0xE1, 0xF6, 0x5C, 0x07, 0xAA, 0x71, 0x6C, 0x13, 0xA4, 0xB1, + 0xB3, 0x66, 0xBF, 0x90, 0x4C, 0x3D, 0xA2, 0xC4, 0x0B, 0xB8, 0x3D, 0x7A, + 0x8C, 0x19, 0xFA, 0xFF, 0x6B, 0xB9, 0x1F, 0x02, 0xCC, 0xB6, 0xD3, 0x0C, + 0x7D, 0x19, 0x1F, 0x47, 0xF9, 0xC7, 0x40, 0x01, 0xFA, 0x46, 0xEA, 0x0B, + 0xD4, 0x02, 0xE0, 0x3D, 0x30, 0x9A, 0x1A, 0x0F, 0xEA, 0xA7, 0x66, 0x55, + 0xF7, 0xCB, 0x28, 0xE2, 0xBB, 0x99, 0xE4, 0x83, 0xC3, 0x43, 0x03, 0xEE, + 0xDC, 0x1F, 0x02, 0x23, 0xDD, 0xD1, 0x2D, 0x39, 0xA4, 0x65, 0x75, 0x03, + 0xEF, 0x37, 0x9C, 0x06, 0xD6, 0xFA, 0xA1, 0x15, 0xF0, 0xDB, 0x17, 0x47, + 0x26, 0x4F, 0x49, 0x03, + ]), + ], + /* package2_fixed_key_modulus: */ + Modulus([ + 0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, + 0x20, 0x69, 0x59, 0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, + 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE, 0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, + 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5, 0x6C, 0x39, 0x7F, 0x41, + 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74, 0x8B, + 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, + 0xD3, 0x48, 0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, + 0xBD, 0xC3, 0x29, 0x90, 0xBE, 0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, + 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32, 0x9A, 0x42, 0x9D, 0x09, 0x8B, + 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A, 0xD7, 0xE1, + 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, + 0x0B, 0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, + 0x9E, 0xF4, 0x46, 0xA3, 0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, + 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9, 0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, + 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47, 0xFD, 0xFA, 0x4C, + 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D, + 0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, + 0x9A, 0x3F, 0xF2, 0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, + 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF, 0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, + 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F, + ]), + ), + ) } pub fn new_dev(key_path: Option<&Path>) -> Result { - Keys::new(key_path, Path::new("dev.keys"), ( - /* nca_hdr_fixed_key_modulus: */ [Modulus([ - 0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, 0xB3, 0x04, 0xA8, 0xA4, - 0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49, - 0x85, 0xE5, 0x8A, 0x9B, 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C, - 0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, 0x0A, 0x50, 0xF2, 0x2B, - 0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4, - 0x49, 0x2F, 0xCF, 0x03, 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47, - 0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, 0x0E, 0x17, 0x3F, 0xFE, - 0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D, - 0xA1, 0xD9, 0x66, 0x20, 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E, - 0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, 0x75, 0x76, 0xBF, 0xB0, - 0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D, - 0x7A, 0xA4, 0x21, 0x55, 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E, - 0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, 0xDE, 0xD8, 0x1B, 0x4B, - 0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E, - 0xEA, 0x7F, 0x86, 0xF3, 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62, - 0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, 0x8F, 0xB9, 0x4A, 0xA9, - ]), Modulus([ - 0x9A, 0xBC, 0x88, 0xBD, 0x0A, 0xBE, 0xD7, 0x0C, 0x9B, 0x42, 0x75, 0x65, 0x38, 0x5E, 0xD1, 0x01, - 0xCD, 0x12, 0xAE, 0xEA, 0xE9, 0x4B, 0xDB, 0xB4, 0x5E, 0x36, 0x10, 0x96, 0xDA, 0x3D, 0x2E, 0x66, - 0xD3, 0x99, 0x13, 0x8A, 0xBE, 0x67, 0x41, 0xC8, 0x93, 0xD9, 0x3E, 0x42, 0xCE, 0x34, 0xCE, 0x96, - 0xFA, 0x0B, 0x23, 0xCC, 0x2C, 0xDF, 0x07, 0x3F, 0x3B, 0x24, 0x4B, 0x12, 0x67, 0x3A, 0x29, 0x36, - 0xA3, 0xAA, 0x06, 0xF0, 0x65, 0xA5, 0x85, 0xBA, 0xFD, 0x12, 0xEC, 0xF1, 0x60, 0x67, 0xF0, 0x8F, - 0xD3, 0x5B, 0x01, 0x1B, 0x1E, 0x84, 0xA3, 0x5C, 0x65, 0x36, 0xF9, 0x23, 0x7E, 0xF3, 0x26, 0x38, - 0x64, 0x98, 0xBA, 0xE4, 0x19, 0x91, 0x4C, 0x02, 0xCF, 0xC9, 0x6D, 0x86, 0xEC, 0x1D, 0x41, 0x69, - 0xDD, 0x56, 0xEA, 0x5C, 0xA3, 0x2A, 0x58, 0xB4, 0x39, 0xCC, 0x40, 0x31, 0xFD, 0xFB, 0x42, 0x74, - 0xF8, 0xEC, 0xEA, 0x00, 0xF0, 0xD9, 0x28, 0xEA, 0xFA, 0x2D, 0x00, 0xE1, 0x43, 0x53, 0xC6, 0x32, - 0xF4, 0xA2, 0x07, 0xD4, 0x5F, 0xD4, 0xCB, 0xAC, 0xCA, 0xFF, 0xDF, 0x84, 0xD2, 0x86, 0x14, 0x3C, - 0xDE, 0x22, 0x75, 0xA5, 0x73, 0xFF, 0x68, 0x07, 0x4A, 0xF9, 0x7C, 0x2C, 0xCC, 0xDE, 0x45, 0xB6, - 0x54, 0x82, 0x90, 0x36, 0x1F, 0x2C, 0x51, 0x96, 0xC5, 0x0A, 0x53, 0x5B, 0xF0, 0x8B, 0x4A, 0xAA, - 0x3B, 0x68, 0x97, 0x19, 0x17, 0x1F, 0x01, 0xB8, 0xED, 0xB9, 0x9A, 0x5E, 0x08, 0xC5, 0x20, 0x1E, - 0x6A, 0x09, 0xF0, 0xE9, 0x73, 0xA3, 0xBE, 0x10, 0x06, 0x02, 0xE9, 0xFB, 0x85, 0xFA, 0x5F, 0x01, - 0xAC, 0x60, 0xE0, 0xED, 0x7D, 0xB9, 0x49, 0xA8, 0x9E, 0x98, 0x7D, 0x91, 0x40, 0x05, 0xCF, 0xF9, - 0x1A, 0xFC, 0x40, 0x22, 0xA8, 0x96, 0x5B, 0xB0, 0xDC, 0x7A, 0xF5, 0xB7, 0xE9, 0x91, 0x4C, 0x49, - ])], - /* acid_fixed_key_modulus: */ [Modulus([ - 0xD6, 0x34, 0xA5, 0x78, 0x6C, 0x68, 0xCE, 0x5A, 0xC2, 0x37, 0x17, 0xF3, 0x82, 0x45, 0xC6, 0x89, - 0xE1, 0x2D, 0x06, 0x67, 0xBF, 0xB4, 0x06, 0x19, 0x55, 0x6B, 0x27, 0x66, 0x0C, 0xA4, 0xB5, 0x87, - 0x81, 0x25, 0xF4, 0x30, 0xBC, 0x53, 0x08, 0x68, 0xA2, 0x48, 0x49, 0x8C, 0x3F, 0x38, 0x40, 0x9C, - 0xC4, 0x26, 0xF4, 0x79, 0xE2, 0xA1, 0x85, 0xF5, 0x5C, 0x7F, 0x58, 0xBA, 0xA6, 0x1C, 0xA0, 0x8B, - 0x84, 0x16, 0x14, 0x6F, 0x85, 0xD9, 0x7C, 0xE1, 0x3C, 0x67, 0x22, 0x1E, 0xFB, 0xD8, 0xA7, 0xA5, - 0x9A, 0xBF, 0xEC, 0x0E, 0xCF, 0x96, 0x7E, 0x85, 0xC2, 0x1D, 0x49, 0x5D, 0x54, 0x26, 0xCB, 0x32, - 0x7C, 0xF6, 0xBB, 0x58, 0x03, 0x80, 0x2B, 0x5D, 0xF7, 0xFB, 0xD1, 0x9D, 0xC7, 0xC6, 0x2E, 0x53, - 0xC0, 0x6F, 0x39, 0x2C, 0x1F, 0xA9, 0x92, 0xF2, 0x4D, 0x7D, 0x4E, 0x74, 0xFF, 0xE4, 0xEF, 0xE4, - 0x7C, 0x3D, 0x34, 0x2A, 0x71, 0xA4, 0x97, 0x59, 0xFF, 0x4F, 0xA2, 0xF4, 0x66, 0x78, 0xD8, 0xBA, - 0x99, 0xE3, 0xE6, 0xDB, 0x54, 0xB9, 0xE9, 0x54, 0xA1, 0x70, 0xFC, 0x05, 0x1F, 0x11, 0x67, 0x4B, - 0x26, 0x8C, 0x0C, 0x3E, 0x03, 0xD2, 0xA3, 0x55, 0x5C, 0x7D, 0xC0, 0x5D, 0x9D, 0xFF, 0x13, 0x2F, - 0xFD, 0x19, 0xBF, 0xED, 0x44, 0xC3, 0x8C, 0xA7, 0x28, 0xCB, 0xE5, 0xE0, 0xB1, 0xA7, 0x9C, 0x33, - 0x8D, 0xB8, 0x6E, 0xDE, 0x87, 0x18, 0x22, 0x60, 0xC4, 0xAE, 0xF2, 0x87, 0x9F, 0xCE, 0x09, 0x5C, - 0xB5, 0x99, 0xA5, 0x9F, 0x49, 0xF2, 0xD7, 0x58, 0xFA, 0xF9, 0xC0, 0x25, 0x7D, 0xD6, 0xCB, 0xF3, - 0xD8, 0x6C, 0xA2, 0x69, 0x91, 0x68, 0x73, 0xB1, 0x94, 0x6F, 0xA3, 0xF3, 0xB9, 0x7D, 0xF8, 0xE0, - 0x72, 0x9E, 0x93, 0x7B, 0x7A, 0xA2, 0x57, 0x60, 0xB7, 0x5B, 0xA9, 0x84, 0xAE, 0x64, 0x88, 0x69 - ]), Modulus([ - 0xBC, 0xA5, 0x6A, 0x7E, 0xEA, 0x38, 0x34, 0x62, 0xA6, 0x10, 0x18, 0x3C, 0xE1, 0x63, 0x7B, 0xF0, - 0xD3, 0x08, 0x8C, 0xF5, 0xC5, 0xC4, 0xC7, 0x93, 0xE9, 0xD9, 0xE6, 0x32, 0xF3, 0xA0, 0xF6, 0x6E, - 0x8A, 0x98, 0x76, 0x47, 0x33, 0x47, 0x65, 0x02, 0x70, 0xDC, 0x86, 0x5F, 0x3D, 0x61, 0x5A, 0x70, - 0xBC, 0x5A, 0xCA, 0xCA, 0x50, 0xAD, 0x61, 0x7E, 0xC9, 0xEC, 0x27, 0xFF, 0xE8, 0x64, 0x42, 0x9A, - 0xEE, 0xBE, 0xC3, 0xD1, 0x0B, 0xC0, 0xE9, 0xBF, 0x83, 0x8D, 0xC0, 0x0C, 0xD8, 0x00, 0x5B, 0x76, - 0x90, 0xD2, 0x4B, 0x30, 0x84, 0x35, 0x8B, 0x1E, 0x20, 0xB7, 0xE4, 0xDC, 0x63, 0xE5, 0xDF, 0xCD, - 0x00, 0x5F, 0x81, 0x5F, 0x67, 0xC5, 0x8B, 0xDF, 0xFC, 0xE1, 0x37, 0x5F, 0x07, 0xD9, 0xDE, 0x4F, - 0xE6, 0x7B, 0xF1, 0xFB, 0xA1, 0x5A, 0x71, 0x40, 0xFE, 0xBA, 0x1E, 0xAE, 0x13, 0x22, 0xD2, 0xFE, - 0x37, 0xA2, 0xB6, 0x8B, 0xAB, 0xEB, 0x84, 0x81, 0x4E, 0x7C, 0x1E, 0x02, 0xD1, 0xFB, 0xD7, 0x5D, - 0x11, 0x84, 0x64, 0xD2, 0x4D, 0xBB, 0x50, 0x00, 0x67, 0x54, 0xE2, 0x77, 0x89, 0xBA, 0x0B, 0xE7, - 0x05, 0x57, 0x9A, 0x22, 0x5A, 0xEC, 0x76, 0x1C, 0xFD, 0xE8, 0xA8, 0x18, 0x16, 0x41, 0x65, 0x03, - 0xFA, 0xC4, 0xA6, 0x31, 0x5C, 0x1A, 0x7F, 0xAB, 0x11, 0xC8, 0x4A, 0x99, 0xB9, 0xE6, 0xCF, 0x62, - 0x21, 0xA6, 0x72, 0x47, 0xDB, 0xBA, 0x96, 0x26, 0x4E, 0x2E, 0xD4, 0x8C, 0x46, 0xD6, 0xA7, 0x1A, - 0x6C, 0x32, 0xA7, 0xDF, 0x85, 0x1C, 0x03, 0xC3, 0x6D, 0xA9, 0xE9, 0x68, 0xF4, 0x17, 0x1E, 0xB2, - 0x70, 0x2A, 0xA1, 0xE5, 0xE1, 0xF3, 0x8F, 0x6F, 0x63, 0xAC, 0xEB, 0x72, 0x0B, 0x4C, 0x4A, 0x36, - 0x3C, 0x60, 0x91, 0x9F, 0x6E, 0x1C, 0x71, 0xEA, 0xD0, 0x78, 0x78, 0xA0, 0x2E, 0xC6, 0x32, 0x6B - ])], - /* package2_fixed_key_modulus: */ Modulus([ - 0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99, - 0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7, - 0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6, - 0xF3, 0xBB, 0x77, 0x87, 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38, - 0x06, 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, 0x51, 0x83, - 0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, 0x1E, 0x68, 0x11, 0x50, 0xA0, - 0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6, - 0xC8, 0x26, 0xE9, 0xFE, 0x06, 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50, - 0x1A, 0xA4, 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, 0xB7, - 0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, 0x69, 0x79, 0x31, 0x42, - 0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E, - 0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8, - 0x6B, 0xAE, 0xC7, 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7, - 0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, 0x90, 0x0C, 0xB4, - 0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46, - 0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B - ]) - )) + Keys::new( + key_path, + Path::new("dev.keys"), + ( + /* nca_hdr_fixed_key_modulus: */ + [ + Modulus([ + 0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, + 0xB3, 0x04, 0xA8, 0xA4, 0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, + 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49, 0x85, 0xE5, 0x8A, 0x9B, + 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C, + 0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, + 0x0A, 0x50, 0xF2, 0x2B, 0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, + 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4, 0x49, 0x2F, 0xCF, 0x03, + 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47, + 0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, + 0x0E, 0x17, 0x3F, 0xFE, 0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, + 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D, 0xA1, 0xD9, 0x66, 0x20, + 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E, + 0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, + 0x75, 0x76, 0xBF, 0xB0, 0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, + 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D, 0x7A, 0xA4, 0x21, 0x55, + 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E, + 0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, + 0xDE, 0xD8, 0x1B, 0x4B, 0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, + 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E, 0xEA, 0x7F, 0x86, 0xF3, + 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62, + 0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, + 0x8F, 0xB9, 0x4A, 0xA9, + ]), + Modulus([ + 0x9A, 0xBC, 0x88, 0xBD, 0x0A, 0xBE, 0xD7, 0x0C, 0x9B, 0x42, 0x75, 0x65, + 0x38, 0x5E, 0xD1, 0x01, 0xCD, 0x12, 0xAE, 0xEA, 0xE9, 0x4B, 0xDB, 0xB4, + 0x5E, 0x36, 0x10, 0x96, 0xDA, 0x3D, 0x2E, 0x66, 0xD3, 0x99, 0x13, 0x8A, + 0xBE, 0x67, 0x41, 0xC8, 0x93, 0xD9, 0x3E, 0x42, 0xCE, 0x34, 0xCE, 0x96, + 0xFA, 0x0B, 0x23, 0xCC, 0x2C, 0xDF, 0x07, 0x3F, 0x3B, 0x24, 0x4B, 0x12, + 0x67, 0x3A, 0x29, 0x36, 0xA3, 0xAA, 0x06, 0xF0, 0x65, 0xA5, 0x85, 0xBA, + 0xFD, 0x12, 0xEC, 0xF1, 0x60, 0x67, 0xF0, 0x8F, 0xD3, 0x5B, 0x01, 0x1B, + 0x1E, 0x84, 0xA3, 0x5C, 0x65, 0x36, 0xF9, 0x23, 0x7E, 0xF3, 0x26, 0x38, + 0x64, 0x98, 0xBA, 0xE4, 0x19, 0x91, 0x4C, 0x02, 0xCF, 0xC9, 0x6D, 0x86, + 0xEC, 0x1D, 0x41, 0x69, 0xDD, 0x56, 0xEA, 0x5C, 0xA3, 0x2A, 0x58, 0xB4, + 0x39, 0xCC, 0x40, 0x31, 0xFD, 0xFB, 0x42, 0x74, 0xF8, 0xEC, 0xEA, 0x00, + 0xF0, 0xD9, 0x28, 0xEA, 0xFA, 0x2D, 0x00, 0xE1, 0x43, 0x53, 0xC6, 0x32, + 0xF4, 0xA2, 0x07, 0xD4, 0x5F, 0xD4, 0xCB, 0xAC, 0xCA, 0xFF, 0xDF, 0x84, + 0xD2, 0x86, 0x14, 0x3C, 0xDE, 0x22, 0x75, 0xA5, 0x73, 0xFF, 0x68, 0x07, + 0x4A, 0xF9, 0x7C, 0x2C, 0xCC, 0xDE, 0x45, 0xB6, 0x54, 0x82, 0x90, 0x36, + 0x1F, 0x2C, 0x51, 0x96, 0xC5, 0x0A, 0x53, 0x5B, 0xF0, 0x8B, 0x4A, 0xAA, + 0x3B, 0x68, 0x97, 0x19, 0x17, 0x1F, 0x01, 0xB8, 0xED, 0xB9, 0x9A, 0x5E, + 0x08, 0xC5, 0x20, 0x1E, 0x6A, 0x09, 0xF0, 0xE9, 0x73, 0xA3, 0xBE, 0x10, + 0x06, 0x02, 0xE9, 0xFB, 0x85, 0xFA, 0x5F, 0x01, 0xAC, 0x60, 0xE0, 0xED, + 0x7D, 0xB9, 0x49, 0xA8, 0x9E, 0x98, 0x7D, 0x91, 0x40, 0x05, 0xCF, 0xF9, + 0x1A, 0xFC, 0x40, 0x22, 0xA8, 0x96, 0x5B, 0xB0, 0xDC, 0x7A, 0xF5, 0xB7, + 0xE9, 0x91, 0x4C, 0x49, + ]), + ], + /* acid_fixed_key_modulus: */ + [ + Modulus([ + 0xD6, 0x34, 0xA5, 0x78, 0x6C, 0x68, 0xCE, 0x5A, 0xC2, 0x37, 0x17, 0xF3, + 0x82, 0x45, 0xC6, 0x89, 0xE1, 0x2D, 0x06, 0x67, 0xBF, 0xB4, 0x06, 0x19, + 0x55, 0x6B, 0x27, 0x66, 0x0C, 0xA4, 0xB5, 0x87, 0x81, 0x25, 0xF4, 0x30, + 0xBC, 0x53, 0x08, 0x68, 0xA2, 0x48, 0x49, 0x8C, 0x3F, 0x38, 0x40, 0x9C, + 0xC4, 0x26, 0xF4, 0x79, 0xE2, 0xA1, 0x85, 0xF5, 0x5C, 0x7F, 0x58, 0xBA, + 0xA6, 0x1C, 0xA0, 0x8B, 0x84, 0x16, 0x14, 0x6F, 0x85, 0xD9, 0x7C, 0xE1, + 0x3C, 0x67, 0x22, 0x1E, 0xFB, 0xD8, 0xA7, 0xA5, 0x9A, 0xBF, 0xEC, 0x0E, + 0xCF, 0x96, 0x7E, 0x85, 0xC2, 0x1D, 0x49, 0x5D, 0x54, 0x26, 0xCB, 0x32, + 0x7C, 0xF6, 0xBB, 0x58, 0x03, 0x80, 0x2B, 0x5D, 0xF7, 0xFB, 0xD1, 0x9D, + 0xC7, 0xC6, 0x2E, 0x53, 0xC0, 0x6F, 0x39, 0x2C, 0x1F, 0xA9, 0x92, 0xF2, + 0x4D, 0x7D, 0x4E, 0x74, 0xFF, 0xE4, 0xEF, 0xE4, 0x7C, 0x3D, 0x34, 0x2A, + 0x71, 0xA4, 0x97, 0x59, 0xFF, 0x4F, 0xA2, 0xF4, 0x66, 0x78, 0xD8, 0xBA, + 0x99, 0xE3, 0xE6, 0xDB, 0x54, 0xB9, 0xE9, 0x54, 0xA1, 0x70, 0xFC, 0x05, + 0x1F, 0x11, 0x67, 0x4B, 0x26, 0x8C, 0x0C, 0x3E, 0x03, 0xD2, 0xA3, 0x55, + 0x5C, 0x7D, 0xC0, 0x5D, 0x9D, 0xFF, 0x13, 0x2F, 0xFD, 0x19, 0xBF, 0xED, + 0x44, 0xC3, 0x8C, 0xA7, 0x28, 0xCB, 0xE5, 0xE0, 0xB1, 0xA7, 0x9C, 0x33, + 0x8D, 0xB8, 0x6E, 0xDE, 0x87, 0x18, 0x22, 0x60, 0xC4, 0xAE, 0xF2, 0x87, + 0x9F, 0xCE, 0x09, 0x5C, 0xB5, 0x99, 0xA5, 0x9F, 0x49, 0xF2, 0xD7, 0x58, + 0xFA, 0xF9, 0xC0, 0x25, 0x7D, 0xD6, 0xCB, 0xF3, 0xD8, 0x6C, 0xA2, 0x69, + 0x91, 0x68, 0x73, 0xB1, 0x94, 0x6F, 0xA3, 0xF3, 0xB9, 0x7D, 0xF8, 0xE0, + 0x72, 0x9E, 0x93, 0x7B, 0x7A, 0xA2, 0x57, 0x60, 0xB7, 0x5B, 0xA9, 0x84, + 0xAE, 0x64, 0x88, 0x69, + ]), + Modulus([ + 0xBC, 0xA5, 0x6A, 0x7E, 0xEA, 0x38, 0x34, 0x62, 0xA6, 0x10, 0x18, 0x3C, + 0xE1, 0x63, 0x7B, 0xF0, 0xD3, 0x08, 0x8C, 0xF5, 0xC5, 0xC4, 0xC7, 0x93, + 0xE9, 0xD9, 0xE6, 0x32, 0xF3, 0xA0, 0xF6, 0x6E, 0x8A, 0x98, 0x76, 0x47, + 0x33, 0x47, 0x65, 0x02, 0x70, 0xDC, 0x86, 0x5F, 0x3D, 0x61, 0x5A, 0x70, + 0xBC, 0x5A, 0xCA, 0xCA, 0x50, 0xAD, 0x61, 0x7E, 0xC9, 0xEC, 0x27, 0xFF, + 0xE8, 0x64, 0x42, 0x9A, 0xEE, 0xBE, 0xC3, 0xD1, 0x0B, 0xC0, 0xE9, 0xBF, + 0x83, 0x8D, 0xC0, 0x0C, 0xD8, 0x00, 0x5B, 0x76, 0x90, 0xD2, 0x4B, 0x30, + 0x84, 0x35, 0x8B, 0x1E, 0x20, 0xB7, 0xE4, 0xDC, 0x63, 0xE5, 0xDF, 0xCD, + 0x00, 0x5F, 0x81, 0x5F, 0x67, 0xC5, 0x8B, 0xDF, 0xFC, 0xE1, 0x37, 0x5F, + 0x07, 0xD9, 0xDE, 0x4F, 0xE6, 0x7B, 0xF1, 0xFB, 0xA1, 0x5A, 0x71, 0x40, + 0xFE, 0xBA, 0x1E, 0xAE, 0x13, 0x22, 0xD2, 0xFE, 0x37, 0xA2, 0xB6, 0x8B, + 0xAB, 0xEB, 0x84, 0x81, 0x4E, 0x7C, 0x1E, 0x02, 0xD1, 0xFB, 0xD7, 0x5D, + 0x11, 0x84, 0x64, 0xD2, 0x4D, 0xBB, 0x50, 0x00, 0x67, 0x54, 0xE2, 0x77, + 0x89, 0xBA, 0x0B, 0xE7, 0x05, 0x57, 0x9A, 0x22, 0x5A, 0xEC, 0x76, 0x1C, + 0xFD, 0xE8, 0xA8, 0x18, 0x16, 0x41, 0x65, 0x03, 0xFA, 0xC4, 0xA6, 0x31, + 0x5C, 0x1A, 0x7F, 0xAB, 0x11, 0xC8, 0x4A, 0x99, 0xB9, 0xE6, 0xCF, 0x62, + 0x21, 0xA6, 0x72, 0x47, 0xDB, 0xBA, 0x96, 0x26, 0x4E, 0x2E, 0xD4, 0x8C, + 0x46, 0xD6, 0xA7, 0x1A, 0x6C, 0x32, 0xA7, 0xDF, 0x85, 0x1C, 0x03, 0xC3, + 0x6D, 0xA9, 0xE9, 0x68, 0xF4, 0x17, 0x1E, 0xB2, 0x70, 0x2A, 0xA1, 0xE5, + 0xE1, 0xF3, 0x8F, 0x6F, 0x63, 0xAC, 0xEB, 0x72, 0x0B, 0x4C, 0x4A, 0x36, + 0x3C, 0x60, 0x91, 0x9F, 0x6E, 0x1C, 0x71, 0xEA, 0xD0, 0x78, 0x78, 0xA0, + 0x2E, 0xC6, 0x32, 0x6B, + ]), + ], + /* package2_fixed_key_modulus: */ + Modulus([ + 0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, + 0xBA, 0x96, 0x99, 0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, + 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7, 0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, + 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6, 0xF3, 0xBB, 0x77, 0x87, + 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38, 0x06, + 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, + 0x51, 0x83, 0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, + 0x1E, 0x68, 0x11, 0x50, 0xA0, 0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, + 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6, 0xC8, 0x26, 0xE9, 0xFE, 0x06, + 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50, 0x1A, 0xA4, + 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, + 0xB7, 0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, + 0x69, 0x79, 0x31, 0x42, 0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, + 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E, 0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, + 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8, 0x6B, 0xAE, 0xC7, + 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7, + 0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, + 0x90, 0x0C, 0xB4, 0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, + 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46, 0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, + 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B, + ]), + ), + ) } + #[allow(clippy::cognitive_complexity)] fn read_from_ini(&mut self, mut file: File) -> Result<(), Error> { let config = ini::Ini::read_from(&mut file)?; let section = config.general_section(); @@ -586,6 +724,7 @@ impl Keys { Ok(()) } + #[allow(clippy::cognitive_complexity)] pub fn write(&self, w: &mut W) -> io::Result<()> { make_key_macros_write!(self, w); single_key!(secure_boot_key); @@ -630,32 +769,52 @@ impl Keys { pub fn derive_keys(&mut self) -> Result<(), Error> { for i in 0..6 { /* Derive the keyblob_keys */ - match (&self.secure_boot_key, &self.tsec_key, &self.keyblob_key_sources[i]) { + match ( + &self.secure_boot_key, + &self.tsec_key, + &self.keyblob_key_sources[i], + ) { (Some(sbk), Some(tsec_key), Some(keyblob_key_source)) => { let tmp = tsec_key.derive_key(&keyblob_key_source.0)?; self.keyblob_keys[i] = Some(sbk.derive_key(&tmp.0)?); - }, - _ => continue + } + _ => continue, } } for i in 0..6 { /* Derive the keyblob mac keys */ match (&self.keyblob_keys[i], &self.keyblob_mac_key_source) { (Some(keyblob_key), Some(keyblob_mac_key_source)) => { - self.keyblob_mac_keys[i] = Some(keyblob_key.derive_key(&keyblob_mac_key_source.0)?); - }, - _ => continue + self.keyblob_mac_keys[i] = + Some(keyblob_key.derive_key(&keyblob_mac_key_source.0)?); + } + _ => continue, } } for i in 0..6 { - match (&self.keyblob_keys[i], &self.keyblob_mac_keys[i], &mut self.encrypted_keyblobs[i], &mut self.keyblobs[i]) { - (Some(keyblob_key), Some(keyblob_mac_key), Some(encrypted_keyblob), ref mut keyblob @ None) => { + match ( + &self.keyblob_keys[i], + &self.keyblob_mac_keys[i], + &mut self.encrypted_keyblobs[i], + &mut self.keyblobs[i], + ) { + ( + Some(keyblob_key), + Some(keyblob_mac_key), + Some(encrypted_keyblob), + ref mut keyblob @ None, + ) => { **keyblob = Some(encrypted_keyblob.decrypt(keyblob_key, keyblob_mac_key, i)?); - }, - (Some(keyblob_key), Some(keyblob_mac_key), ref mut encrypted_keyblob @ None, Some(keyblob)) => { + } + ( + Some(keyblob_key), + Some(keyblob_mac_key), + ref mut encrypted_keyblob @ None, + Some(keyblob), + ) => { **encrypted_keyblob = Some(keyblob.encrypt(keyblob_key, keyblob_mac_key, i)?); - }, - _ => continue + } + _ => continue, } } for i in 0..6 { @@ -674,8 +833,8 @@ impl Keys { match (&self.tsec_root_key[i - 6], &self.master_kek_sources[i]) { (Some(tsec_root_key), Some(master_kek_source)) => { self.master_keks[i] = Some(tsec_root_key.derive_key(&master_kek_source.0)?); - }, - _ => continue + } + _ => continue, } } for i in 0..0x20 { @@ -683,30 +842,69 @@ impl Keys { match (&self.master_key_source, &self.master_keks[i]) { (Some(master_key_source), Some(master_kek)) => { self.master_keys[i] = Some(master_kek.derive_key(&master_key_source.0)?); - }, - _ => continue + } + _ => continue, } } for i in 0..0x20 { if let Some(master_key) = &self.master_keys[i] { /* Derive key area encryption key */ - match (&self.key_area_key_application_source, &self.aes_kek_generation_source, &self.aes_key_generation_source) { - (Some(key_area_key_application_source), Some(aes_kek_generation_source), Some(aes_key_generation_source)) => { - self.key_area_key_application[i] = Some(generate_kek(key_area_key_application_source, master_key, aes_kek_generation_source, aes_key_generation_source)?); - }, - _ => continue + match ( + &self.key_area_key_application_source, + &self.aes_kek_generation_source, + &self.aes_key_generation_source, + ) { + ( + Some(key_area_key_application_source), + Some(aes_kek_generation_source), + Some(aes_key_generation_source), + ) => { + self.key_area_key_application[i] = Some(generate_kek( + key_area_key_application_source, + master_key, + aes_kek_generation_source, + aes_key_generation_source, + )?); + } + _ => continue, } - match (&self.key_area_key_ocean_source, &self.aes_kek_generation_source, &self.aes_key_generation_source) { - (Some(key_area_key_ocean_source), Some(aes_kek_generation_source), Some(aes_key_generation_source)) => { - self.key_area_key_ocean[i] = Some(generate_kek(key_area_key_ocean_source, master_key, aes_kek_generation_source, aes_key_generation_source)?); - }, - _ => continue + match ( + &self.key_area_key_ocean_source, + &self.aes_kek_generation_source, + &self.aes_key_generation_source, + ) { + ( + Some(key_area_key_ocean_source), + Some(aes_kek_generation_source), + Some(aes_key_generation_source), + ) => { + self.key_area_key_ocean[i] = Some(generate_kek( + key_area_key_ocean_source, + master_key, + aes_kek_generation_source, + aes_key_generation_source, + )?); + } + _ => continue, } - match (&self.key_area_key_system_source, &self.aes_kek_generation_source, &self.aes_key_generation_source) { - (Some(key_area_key_system_source), Some(aes_kek_generation_source), Some(aes_key_generation_source)) => { - self.key_area_key_system[i] = Some(generate_kek(key_area_key_system_source, master_key, aes_kek_generation_source, aes_key_generation_source)?); - }, - _ => continue + match ( + &self.key_area_key_system_source, + &self.aes_kek_generation_source, + &self.aes_key_generation_source, + ) { + ( + Some(key_area_key_system_source), + Some(aes_kek_generation_source), + Some(aes_key_generation_source), + ) => { + self.key_area_key_system[i] = Some(generate_kek( + key_area_key_system_source, + master_key, + aes_kek_generation_source, + aes_key_generation_source, + )?); + } + _ => continue, } /* Derive titlekek */ if let Some(titlekek_source) = &self.titlekek_source { @@ -720,25 +918,57 @@ impl Keys { /* Derive Header Key */ #[allow(clippy::single_match)] - match (i, &self.header_kek_source, &self.header_key_source, &self.aes_kek_generation_source, &self.aes_key_generation_source) { - (0, Some(header_kek_source), Some(header_key_source), Some(aes_kek_generation_source), Some(aes_key_generation_source)) => { - let header_kek = generate_kek(&header_kek_source, master_key, &aes_kek_generation_source, &aes_key_generation_source)?; + match ( + i, + &self.header_kek_source, + &self.header_key_source, + &self.aes_kek_generation_source, + &self.aes_key_generation_source, + ) { + ( + 0, + Some(header_kek_source), + Some(header_key_source), + Some(aes_kek_generation_source), + Some(aes_key_generation_source), + ) => { + let header_kek = generate_kek( + &header_kek_source, + master_key, + &aes_kek_generation_source, + &aes_key_generation_source, + )?; self.header_key = Some(header_kek.derive_xts_key(&header_key_source.0)?); - }, - _ => () + } + _ => (), } /* Derive SD Card key */ - match (&self.sd_card_kek_source, &self.aes_kek_generation_source, &self.aes_key_generation_source) { - (Some(sd_card_kek_source), Some(aes_kek_generation_source), Some(aes_key_generation_source)) => { - let sd_kek = generate_kek(sd_card_kek_source, master_key, aes_kek_generation_source, aes_key_generation_source)?; + match ( + &self.sd_card_kek_source, + &self.aes_kek_generation_source, + &self.aes_key_generation_source, + ) { + ( + Some(sd_card_kek_source), + Some(aes_kek_generation_source), + Some(aes_key_generation_source), + ) => { + let sd_kek = generate_kek( + sd_card_kek_source, + master_key, + aes_kek_generation_source, + aes_key_generation_source, + )?; if let Some(sd_card_save_key_source) = &self.sd_card_save_key_source { - self.sd_card_save_key = Some(sd_kek.derive_xts_key(&sd_card_save_key_source.0)?); + self.sd_card_save_key = + Some(sd_kek.derive_xts_key(&sd_card_save_key_source.0)?); } if let Some(sd_card_nca_key_source) = &self.sd_card_nca_key_source { - self.sd_card_nca_key = Some(sd_kek.derive_xts_key(&sd_card_nca_key_source.0)?); + self.sd_card_nca_key = + Some(sd_kek.derive_xts_key(&sd_card_nca_key_source.0)?); } - }, - _ => continue + } + _ => continue, } } } diff --git a/src/utils.rs b/src/utils.rs index 3a62d02..3b1b3f4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,14 +1,12 @@ +use core::ops::{BitAnd, Not}; use num_traits::Num; -use core::ops::{Not, BitAnd}; use std::io; -pub fn align_down + BitAnd + Copy>(addr: T, align: T) -> T -{ +pub fn align_down + BitAnd + Copy>(addr: T, align: T) -> T { addr & !(align - T::one()) } -pub fn align_up + BitAnd + Copy>(addr: T, align: T) -> T -{ +pub fn align_up + BitAnd + Copy>(addr: T, align: T) -> T { align_down(addr + (align - T::one()), align) } @@ -18,7 +16,9 @@ pub trait TryClone: Sized { } impl TryClone for std::fs::File { - fn try_clone(&self) -> std::io::Result { std::fs::File::try_clone(&self) } + fn try_clone(&self) -> std::io::Result { + std::fs::File::try_clone(&self) + } } pub struct ReadRange { @@ -32,12 +32,13 @@ impl ReadRange { pub fn new(stream: R, start_from: u64, max_size: u64) -> ReadRange { ReadRange { inner: stream, - start_from: start_from, + start_from, size: max_size, - inner_pos: 0 + inner_pos: 0, } } + #[allow(unused)] pub fn pos_in_stream(&self) -> u64 { self.start_from + self.inner_pos } @@ -64,18 +65,24 @@ impl io::Seek for ReadRange { if let Some(s) = self.inner_pos.checked_sub(-val as u64) { s } else { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "Seek before position 0")); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Seek before position 0", + )); } } else { self.inner_pos + val as u64 } - }, + } io::SeekFrom::End(val) => { if val < 0 { if let Some(s) = self.size.checked_sub(-val as u64) { s } else { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "Seek before position 0")); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Seek before position 0", + )); } } else { self.size + val as u64 @@ -83,7 +90,9 @@ impl io::Seek for ReadRange { } }; - let newpos = self.inner.seek(io::SeekFrom::Start(self.start_from + new_inner_pos))?; + let newpos = self + .inner + .seek(io::SeekFrom::Start(self.start_from + new_inner_pos))?; self.inner_pos = newpos - self.start_from; Ok(self.inner_pos) }