diff --git a/src/de/mas/wiiu/jnus/NUSTitleConfig.java b/src/de/mas/wiiu/jnus/NUSTitleConfig.java index 4f10af7..7099b07 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleConfig.java +++ b/src/de/mas/wiiu/jnus/NUSTitleConfig.java @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (C) 2016-2018 Maschell + * Copyright (C) 2016-2019 Maschell * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,23 +17,11 @@ package de.mas.wiiu.jnus; import de.mas.wiiu.jnus.entities.Ticket; -import de.mas.wiiu.jnus.implementations.woomy.WoomyInfo; -import de.mas.wiiu.jnus.implementations.wud.parser.WUDGIPartitionTitle; -import de.mas.wiiu.jnus.implementations.wud.parser.WUDGamePartition; -import de.mas.wiiu.jnus.implementations.wud.parser.WUDInfo; import lombok.Data; @Data public class NUSTitleConfig { - private String inputPath; - private WUDGamePartition WUDGamePartition = null; - private WUDGIPartitionTitle WUDGIPartitionTitle = null; - private WUDInfo WUDInfo; private Ticket ticket; - - private int version = Settings.LATEST_TMD_VERSION; - private long titleID = 0x0L; - - private WoomyInfo woomyInfo; private boolean noDecryption; + private byte[] commonKey; } diff --git a/src/de/mas/wiiu/jnus/NUSTitleLoader.java b/src/de/mas/wiiu/jnus/NUSTitleLoader.java index 948cb7c..d858111 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleLoader.java +++ b/src/de/mas/wiiu/jnus/NUSTitleLoader.java @@ -16,8 +16,13 @@ ****************************************************************************/ package de.mas.wiiu.jnus; +import java.io.IOException; import java.io.InputStream; +import java.text.ParseException; +import java.util.Arrays; import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; import de.mas.wiiu.jnus.entities.TMD; import de.mas.wiiu.jnus.entities.Ticket; @@ -25,19 +30,19 @@ import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.entities.fst.FST; import de.mas.wiiu.jnus.implementations.NUSDataProvider; import de.mas.wiiu.jnus.utils.StreamUtils; +import de.mas.wiiu.jnus.utils.Utils; import de.mas.wiiu.jnus.utils.cryptography.AESDecryption; -import lombok.extern.java.Log; -@Log -abstract class NUSTitleLoader { - protected NUSTitleLoader() { +public class NUSTitleLoader { + private NUSTitleLoader() { // should be empty } - public NUSTitle loadNusTitle(NUSTitleConfig config) throws Exception { + public static NUSTitle loadNusTitle(NUSTitleConfig config, Supplier dataProviderFunction) + throws IOException, ParseException { NUSTitle result = new NUSTitle(); - NUSDataProvider dataProvider = getDataProvider(result, config); + NUSDataProvider dataProvider = dataProviderFunction.get(); result.setDataProvider(dataProvider); byte[] tmdData = dataProvider.getRawTMD().orElseThrow(() -> new ParseException("No TMD data found", 0)); @@ -79,6 +84,4 @@ abstract class NUSTitleLoader { return result; } - - protected abstract NUSDataProvider getDataProvider(NUSTitle title, NUSTitleConfig config); } diff --git a/src/de/mas/wiiu/jnus/NUSTitleLoaderLocal.java b/src/de/mas/wiiu/jnus/NUSTitleLoaderLocal.java index 79b954a..557412f 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleLoaderLocal.java +++ b/src/de/mas/wiiu/jnus/NUSTitleLoaderLocal.java @@ -16,35 +16,34 @@ ****************************************************************************/ package de.mas.wiiu.jnus; +import java.io.IOException; +import java.text.ParseException; + import de.mas.wiiu.jnus.entities.Ticket; -import de.mas.wiiu.jnus.implementations.NUSDataProvider; import de.mas.wiiu.jnus.implementations.NUSDataProviderLocal; -public final class NUSTitleLoaderLocal extends NUSTitleLoader { +public final class NUSTitleLoaderLocal { - private NUSTitleLoaderLocal() { - super(); + public static NUSTitle loadNUSTitle(String inputPath, byte[] commonKey) throws Exception { + return loadNUSTitle(inputPath, null, commonKey); } - public static NUSTitle loadNUSTitle(String inputPath) throws Exception { - return loadNUSTitle(inputPath, null); + public static NUSTitle loadNUSTitle(String inputPath, Ticket ticket) throws IOException, ParseException { + return loadNUSTitle(inputPath, ticket, null); } - public static NUSTitle loadNUSTitle(String inputPath, Ticket ticket) throws Exception { - NUSTitleLoader loader = new NUSTitleLoaderLocal(); + public static NUSTitle loadNUSTitle(String inputPath, Ticket ticket, byte[] commonKey) throws IOException, ParseException { NUSTitleConfig config = new NUSTitleConfig(); + config.setCommonKey(commonKey); + if (ticket != null) { config.setTicket(ticket); + } else if (commonKey == null) { + throw new IOException("Ticket was null and no commonKey was given"); } - config.setInputPath(inputPath); - return loader.loadNusTitle(config); - } - - @Override - protected NUSDataProvider getDataProvider(NUSTitle title, NUSTitleConfig config) { - return new NUSDataProviderLocal(title, config.getInputPath()); + return NUSTitleLoader.loadNusTitle(config, () -> new NUSDataProviderLocal(inputPath)); } } diff --git a/src/de/mas/wiiu/jnus/NUSTitleLoaderLocalBackup.java b/src/de/mas/wiiu/jnus/NUSTitleLoaderLocalBackup.java index e7cc624..b7f3b1a 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleLoaderLocalBackup.java +++ b/src/de/mas/wiiu/jnus/NUSTitleLoaderLocalBackup.java @@ -18,25 +18,14 @@ package de.mas.wiiu.jnus; import de.mas.wiiu.jnus.entities.Ticket; -import de.mas.wiiu.jnus.implementations.NUSDataProvider; import de.mas.wiiu.jnus.implementations.NUSDataProviderLocalBackup; -public final class NUSTitleLoaderLocalBackup extends NUSTitleLoader { +public final class NUSTitleLoaderLocalBackup { private NUSTitleLoaderLocalBackup() { - super(); - } - public static NUSTitle loadNUSTitle(String inputPath) throws Exception { - return loadNUSTitle(inputPath, (short) Settings.LATEST_TMD_VERSION); } - - public static NUSTitle loadNUSTitle(String inputPath, short titleVersion) throws Exception { - return loadNUSTitle(inputPath, titleVersion, null); - } - public static NUSTitle loadNUSTitle(String inputPath, short titleVersion, Ticket ticket) throws Exception { - NUSTitleLoader loader = new NUSTitleLoaderLocalBackup(); NUSTitleConfig config = new NUSTitleConfig(); if (ticket != null) { @@ -45,15 +34,7 @@ public final class NUSTitleLoaderLocalBackup extends NUSTitleLoader { config.setNoDecryption(true); } - config.setVersion(titleVersion); - config.setInputPath(inputPath); - - return loader.loadNusTitle(config); - } - - @Override - protected NUSDataProvider getDataProvider(NUSTitle title, NUSTitleConfig config) { - return new NUSDataProviderLocalBackup(title, config.getInputPath(), (short) config.getVersion()); + return NUSTitleLoader.loadNusTitle(config, () -> new NUSDataProviderLocalBackup(inputPath, titleVersion)); } } diff --git a/src/de/mas/wiiu/jnus/NUSTitleLoaderRemote.java b/src/de/mas/wiiu/jnus/NUSTitleLoaderRemote.java index da93cbc..d92e6dc 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleLoaderRemote.java +++ b/src/de/mas/wiiu/jnus/NUSTitleLoaderRemote.java @@ -16,22 +16,23 @@ ****************************************************************************/ package de.mas.wiiu.jnus; +import java.io.IOException; +import java.text.ParseException; + import de.mas.wiiu.jnus.entities.Ticket; -import de.mas.wiiu.jnus.implementations.NUSDataProvider; import de.mas.wiiu.jnus.implementations.NUSDataProviderRemote; -public final class NUSTitleLoaderRemote extends NUSTitleLoader { +public final class NUSTitleLoaderRemote { private NUSTitleLoaderRemote() { - super(); } - public static NUSTitle loadNUSTitle(long titleID) throws Exception { - return loadNUSTitle(titleID, Settings.LATEST_TMD_VERSION, null); + public static NUSTitle loadNUSTitle(long titleID, byte[] commonKey) throws Exception { + return loadNUSTitle(titleID, Settings.LATEST_TMD_VERSION, commonKey); } - public static NUSTitle loadNUSTitle(long titleID, int version) throws Exception { - return loadNUSTitle(titleID, version, null); + public static NUSTitle loadNUSTitle(long titleID, int version, byte[] commonKey) throws Exception { + return loadNUSTitle(titleID, version, null, false, commonKey); } public static NUSTitle loadNUSTitle(long titleID, Ticket ticket) throws Exception { @@ -39,24 +40,20 @@ public final class NUSTitleLoaderRemote extends NUSTitleLoader { } public static NUSTitle loadNUSTitle(long titleID, int version, Ticket ticket) throws Exception { - return loadNUSTitle(titleID, version, ticket, false); + return loadNUSTitle(titleID, version, ticket, false, null); } - public static NUSTitle loadNUSTitle(long titleID, int version, Ticket ticket, boolean noEncryption) throws Exception { - NUSTitleLoader loader = new NUSTitleLoaderRemote(); + public static NUSTitle loadNUSTitle(long titleID, int version, Ticket ticket, boolean noEncryption, byte[] commonKey) throws IOException, ParseException { NUSTitleConfig config = new NUSTitleConfig(); - config.setVersion(version); - config.setTitleID(titleID); config.setTicket(ticket); config.setNoDecryption(noEncryption); + config.setCommonKey(commonKey); + if (ticket == null && !noEncryption && commonKey == null) { + throw new IOException("Ticket was null and no commonKey was given"); + } - return loader.loadNusTitle(config); - } - - @Override - protected NUSDataProvider getDataProvider(NUSTitle title, NUSTitleConfig config) { - return new NUSDataProviderRemote(title, config.getVersion(), config.getTitleID()); + return NUSTitleLoader.loadNusTitle(config, () -> new NUSDataProviderRemote(version, titleID)); } } diff --git a/src/de/mas/wiiu/jnus/NUSTitleLoaderWoomy.java b/src/de/mas/wiiu/jnus/NUSTitleLoaderWoomy.java index 6e2fbfb..dfdcf8c 100644 --- a/src/de/mas/wiiu/jnus/NUSTitleLoaderWoomy.java +++ b/src/de/mas/wiiu/jnus/NUSTitleLoaderWoomy.java @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (C) 2016-2018 Maschell + * Copyright (C) 2016-2019 Maschell * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,32 +17,29 @@ package de.mas.wiiu.jnus; import java.io.File; +import java.io.IOException; +import java.text.ParseException; + +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; -import de.mas.wiiu.jnus.implementations.NUSDataProvider; import de.mas.wiiu.jnus.implementations.NUSDataProviderWoomy; import de.mas.wiiu.jnus.implementations.woomy.WoomyInfo; import de.mas.wiiu.jnus.implementations.woomy.WoomyParser; -import lombok.extern.java.Log; -@Log -public final class NUSTitleLoaderWoomy extends NUSTitleLoader { +public final class NUSTitleLoaderWoomy { - public static NUSTitle loadNUSTitle(String inputFile) throws Exception { - NUSTitleLoaderWoomy loader = new NUSTitleLoaderWoomy(); + private NUSTitleLoaderWoomy() { + + } + + public static NUSTitle loadNUSTitle(String inputFile) throws IOException, ParserConfigurationException, SAXException, ParseException { NUSTitleConfig config = new NUSTitleConfig(); WoomyInfo woomyInfo = WoomyParser.createWoomyInfo(new File(inputFile)); - if (woomyInfo == null) { - log.info("Created woomy is null."); - return null; - } - config.setWoomyInfo(woomyInfo); - return loader.loadNusTitle(config); - } - @Override - protected NUSDataProvider getDataProvider(NUSTitle title, NUSTitleConfig config) { - return new NUSDataProviderWoomy(title, config.getWoomyInfo()); + return NUSTitleLoader.loadNusTitle(config, () -> new NUSDataProviderWoomy(woomyInfo)); } } diff --git a/src/de/mas/wiiu/jnus/Settings.java b/src/de/mas/wiiu/jnus/Settings.java index 9b08869..0d97cbf 100644 --- a/src/de/mas/wiiu/jnus/Settings.java +++ b/src/de/mas/wiiu/jnus/Settings.java @@ -31,6 +31,5 @@ public class Settings { public static final String USER_AGENT = "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.28 (KHTML, like Gecko) NX/3.0.3.12.12 NintendoBrowser/3.0.0.9561.US"; public static final boolean ALLOW_PARALLELISATION = true; - public static byte[] commonKey = new byte[0x10]; public static int WIIU_DECRYPTED_AREA_OFFSET = 0x18000; } diff --git a/src/de/mas/wiiu/jnus/entities/Ticket.java b/src/de/mas/wiiu/jnus/entities/Ticket.java index adfdad4..35a867d 100644 --- a/src/de/mas/wiiu/jnus/entities/Ticket.java +++ b/src/de/mas/wiiu/jnus/entities/Ticket.java @@ -22,7 +22,6 @@ import java.nio.ByteBuffer; import java.nio.file.Files; import java.util.Arrays; -import de.mas.wiiu.jnus.Settings; import de.mas.wiiu.jnus.utils.Utils; import de.mas.wiiu.jnus.utils.cryptography.AESDecryption; import lombok.Getter; @@ -44,17 +43,17 @@ public final class Ticket { this.IV = IV; } - public static Ticket parseTicket(File ticket) throws IOException { + public static Ticket parseTicket(File ticket, byte[] commonKey) throws IOException { if (ticket == null || !ticket.exists()) { log.warning("Ticket input file null or doesn't exist."); - return null; + throw new IOException("Ticket input file null or doesn't exist."); } - return parseTicket(Files.readAllBytes(ticket.toPath())); + return parseTicket(Files.readAllBytes(ticket.toPath()), commonKey); } - public static Ticket parseTicket(byte[] ticket) throws IOException { + public static Ticket parseTicket(byte[] ticket, byte[] commonKey) throws IOException { if (ticket == null) { - return null; + throw new IOException("Ticket input file null or doesn't exist."); } ByteBuffer buffer = ByteBuffer.allocate(ticket.length); @@ -69,20 +68,20 @@ public final class Ticket { buffer.position(POSITION_TITLEID); long titleID = buffer.getLong(); - Ticket result = createTicket(encryptedKey, titleID); + Ticket result = createTicket(encryptedKey, titleID, commonKey); return result; } - public static Ticket createTicket(byte[] encryptedKey, long titleID) { + public static Ticket createTicket(byte[] encryptedKey, long titleID, byte[] commonKey) { byte[] IV = ByteBuffer.allocate(0x10).putLong(titleID).array(); - byte[] decryptedKey = calculateDecryptedKey(encryptedKey, IV); + byte[] decryptedKey = calculateDecryptedKey(encryptedKey, IV, commonKey); return new Ticket(encryptedKey, decryptedKey, IV); } - private static byte[] calculateDecryptedKey(byte[] encryptedKey, byte[] IV) { - AESDecryption decryption = new AESDecryption(Settings.commonKey, IV); + private static byte[] calculateDecryptedKey(byte[] encryptedKey, byte[] IV, byte[] commonKey) { + AESDecryption decryption = new AESDecryption(commonKey, IV); return decryption.decrypt(encryptedKey); } @@ -107,4 +106,5 @@ public final class Ticket { public String toString() { return "Ticket [encryptedKey=" + Utils.ByteArrayToString(encryptedKey) + ", decryptedKey=" + Utils.ByteArrayToString(decryptedKey) + "]"; } + }