diff --git a/src/de/mas/wiiu/jnus/entities/TMD.java b/src/de/mas/wiiu/jnus/entities/TMD.java index 04005d8..da756e5 100644 --- a/src/de/mas/wiiu/jnus/entities/TMD.java +++ b/src/de/mas/wiiu/jnus/entities/TMD.java @@ -4,7 +4,9 @@ import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import de.mas.wiiu.jnus.entities.content.Content; @@ -29,6 +31,11 @@ public final class TMD { private static final int CONTENT_INFO_OFFSET = 0x204; private static final int CONTENT_OFFSET = 0xB04; + + private static final int CERT1_LENGTH = 0x400; + private static final int CERT2_LENGTH = 0x300; + + @Getter private final int signatureType; // 0x000 @Getter private final byte[] signature; // 0x004 @@ -47,6 +54,9 @@ public final class TMD { @Getter private final short bootIndex; // 0x1E0 @Getter private final byte[] SHA2; // 0x1E4 @Getter private final ContentInfo[] contentInfos; + @Getter private byte[] cert1; + @Getter private byte[] cert2; + private final Map contentToIndex = new HashMap<>(); private final Map contentToID = new HashMap<>(); @@ -69,6 +79,8 @@ public final class TMD { this.bootIndex = param.getBootIndex(); this.SHA2 = param.getSHA2(); this.contentInfos = param.getContentInfos(); + this.cert1 = param.getCert1(); + this.cert2 = param.getCert2(); } public static TMD parseTMD(File tmd) throws IOException { @@ -84,6 +96,8 @@ public final class TMD { byte[] issuer = new byte[ISSUER_LENGTH]; byte[] reserved = new byte[RESERVED_LENGTH]; byte[] SHA2 = new byte[SHA2_LENGTH]; + byte[] cert1 = new byte[CERT1_LENGTH]; + byte[] cert2 = new byte[CERT2_LENGTH]; ContentInfo[] contentInfos = new ContentInfo[CONTENT_INFO_ARRAY_SIZE]; @@ -136,6 +150,28 @@ public final class TMD { contentInfos[i] = ContentInfo.parseContentInfo(contentInfo); } + List contentList = new ArrayList<>(); + // Get Contents + for (int i = 0; i < contentCount; i++) { + buffer.position(CONTENT_OFFSET + (Content.CONTENT_SIZE * i)); + byte[] content = new byte[Content.CONTENT_SIZE]; + buffer.get(content, 0, Content.CONTENT_SIZE); + Content c = Content.parseContent(content); + contentList.add(c); + } + + try{ + buffer.get(cert2, 0, CERT2_LENGTH); + }catch(Exception e){ + + } + + try{ + buffer.get(cert1, 0, CERT1_LENGTH); + }catch(Exception e){ + + } + TMDParam param = new TMDParam(); param.setSignatureType(signatureType); param.setSignature(signature); @@ -152,15 +188,12 @@ public final class TMD { param.setBootIndex(bootIndex); param.setSHA2(SHA2); param.setContentInfos(contentInfos); + param.setCert1(cert1); + param.setCert2(cert2); TMD result = new TMD(param); - - // Get Contents - for (int i = 0; i < contentCount; i++) { - buffer.position(CONTENT_OFFSET + (Content.CONTENT_SIZE * i)); - byte[] content = new byte[Content.CONTENT_SIZE]; - buffer.get(content, 0, Content.CONTENT_SIZE); - Content c = Content.parseContent(content); + + for(Content c : contentList){ result.setContentToIndex(c.getIndex(), c); result.setContentToID(c.getID(), c); } @@ -222,5 +255,7 @@ public final class TMD { private short bootIndex; // 0x1E0 private byte[] SHA2; // 0x1E4 private ContentInfo[] contentInfos; // + private byte[] cert1; + private byte[] cert2; } } diff --git a/src/de/mas/wiiu/jnus/implementations/NUSDataProviderRemote.java b/src/de/mas/wiiu/jnus/implementations/NUSDataProviderRemote.java index b094814..e4d68f0 100644 --- a/src/de/mas/wiiu/jnus/implementations/NUSDataProviderRemote.java +++ b/src/de/mas/wiiu/jnus/implementations/NUSDataProviderRemote.java @@ -1,9 +1,14 @@ package de.mas.wiiu.jnus.implementations; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.logging.Logger; import de.mas.wiiu.jnus.NUSTitle; +import de.mas.wiiu.jnus.Settings; +import de.mas.wiiu.jnus.entities.TMD; import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.utils.download.NUSDownloadService; import lombok.Getter; @@ -56,7 +61,22 @@ public class NUSDataProviderRemote extends NUSDataProvider { @Override public byte[] getRawCert() throws IOException { - return new byte[0]; // TODO: needs to be implemented + NUSDownloadService downloadService = NUSDownloadService.getDefaultInstance(); + byte[] defaultCert = downloadService.downloadDefaultCertToByteArray(); + + TMD tmd = getNUSTitle().getTMD(); + byte[] result = new byte[0]; + try{ + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + fos.write(tmd.getCert1()); + fos.write(tmd.getCert2()); + fos.write(defaultCert); + result = fos.toByteArray(); + fos.close(); + }catch(Exception e){ + e.printStackTrace(); + } + return result; } @Override diff --git a/src/de/mas/wiiu/jnus/utils/download/NUSDownloadService.java b/src/de/mas/wiiu/jnus/utils/download/NUSDownloadService.java index 3f3e11e..bbebe29 100644 --- a/src/de/mas/wiiu/jnus/utils/download/NUSDownloadService.java +++ b/src/de/mas/wiiu/jnus/utils/download/NUSDownloadService.java @@ -1,9 +1,12 @@ package de.mas.wiiu.jnus.utils.download; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -14,6 +17,8 @@ public final class NUSDownloadService extends Downloader { private static Map instances = new HashMap<>(); private final String URL_BASE; + + private byte[] defaultCertTicket = null; private NUSDownloadService(String URL) { this.URL_BASE = URL; @@ -30,6 +35,14 @@ public final class NUSDownloadService extends Downloader { } return instances.get(URL); } + + public byte[] getDefaultCert() throws IOException { + if(defaultCertTicket == null){ + byte [] ticket = downloadTicketToByteArray(0x000500101000400AL); //Downloading cetk from OSv10 + defaultCertTicket = Arrays.copyOfRange(ticket, 0x350, 0x350+0x300); + } + return defaultCertTicket; + } public byte[] downloadTMDToByteArray(long titleID, int version) throws IOException { String version_suf = ""; @@ -37,6 +50,13 @@ public final class NUSDownloadService extends Downloader { String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/tmd" + version_suf; return downloadFileToByteArray(URL); } + + /** + * For the cert we need a part from a ticket. For this we simply load a public ticket and use it. + */ + public byte[] downloadDefaultCertToByteArray() throws IOException { + return getDefaultCert(); + } public byte[] downloadTicketToByteArray(long titleID) throws IOException { String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/cetk";