From e93a238be910ebc18fd5b75fa68cd0cad8b87b85 Mon Sep 17 00:00:00 2001 From: Xpl0itU <24777100+Xpl0itU@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:34:18 +0200 Subject: [PATCH] Add support for Wii's certificate generation --- certificate.go | 27 +++------------------------ cmd/WiiUDownloader/mainwindow.go | 22 ++++------------------ decryption.go | 2 +- downloader.go | 4 ++-- tmd.go | 20 +++++++++++++++++++- 5 files changed, 29 insertions(+), 46 deletions(-) diff --git a/certificate.go b/certificate.go index 8cd351e..ec8d896 100644 --- a/certificate.go +++ b/certificate.go @@ -10,23 +10,6 @@ import ( var cetkData []byte -func getCert(tmdData []byte, id int, numContents uint16) ([]byte, error) { // TODO: Add support for Wii's TMD - var certSlice []byte - if len(tmdData) == int((0x0B04+0x30*numContents+0xA00)-0x300) { - certSlice = tmdData[0x0B04+0x30*numContents : 0x0B04+0x30*numContents+0xA00-0x300] - } else { - certSlice = tmdData[0x0B04+0x30*numContents : 0x0B04+0x30*numContents+0xA00] - } - switch id { - case 0: - return certSlice[:0x400], nil - case 1: - return certSlice[0x400 : 0x400+0x300], nil - default: - return nil, fmt.Errorf("invalid id: %d", id) - } -} - func getDefaultCert(progressReporter ProgressReporter, client *http.Client) ([]byte, error) { if len(cetkData) >= 0x350+0x300 { return cetkData[0x350 : 0x350+0x300], nil @@ -50,20 +33,16 @@ func getDefaultCert(progressReporter ProgressReporter, client *http.Client) ([]b return nil, fmt.Errorf("failed to download OSv10 cetk, length: %d", len(cetkData)) } -func GenerateCert(tmdData []byte, contentCount uint16, progressReporter ProgressReporter, client *http.Client) (bytes.Buffer, error) { +func GenerateCert(tmd *TMD, progressReporter ProgressReporter, client *http.Client) (bytes.Buffer, error) { cert := bytes.Buffer{} - cert0, err := getCert(tmdData, 0, contentCount) - if err != nil { + if _, err := cert.Write(tmd.Certificate1); err != nil { return bytes.Buffer{}, err } - cert.Write(cert0) - cert1, err := getCert(tmdData, 1, contentCount) - if err != nil { + if _, err := cert.Write(tmd.Certificate2); err != nil { return bytes.Buffer{}, err } - cert.Write(cert1) defaultCert, err := getDefaultCert(progressReporter, client) if err != nil { diff --git a/cmd/WiiUDownloader/mainwindow.go b/cmd/WiiUDownloader/mainwindow.go index 62003dc..d9d1fd6 100644 --- a/cmd/WiiUDownloader/mainwindow.go +++ b/cmd/WiiUDownloader/mainwindow.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "context" "encoding/binary" "fmt" @@ -242,29 +241,16 @@ func (mw *MainWindow) ShowAll() { return } - var contentCount uint16 - if err := binary.Read(bytes.NewReader(tmdData[478:480]), binary.BigEndian, &contentCount); err != nil { - return - } + tmd, err := wiiudownloader.ParseTMD(tmdData) - var titleVersion uint16 - if err := binary.Read(bytes.NewReader(tmdData[476:478]), binary.BigEndian, &titleVersion); err != nil { - return - } - - var titleID uint64 - if err := binary.Read(bytes.NewReader(tmdData[0x018C:0x0194]), binary.BigEndian, &titleID); err != nil { - return - } - - titleKey, err := wiiudownloader.GenerateKey(fmt.Sprintf("%016x", titleID)) + titleKey, err := wiiudownloader.GenerateKey(fmt.Sprintf("%016x", tmd.TitleID)) if err != nil { return } - wiiudownloader.GenerateTicket(filepath.Join(parentDir, "title.tik"), titleID, titleKey, titleVersion) + wiiudownloader.GenerateTicket(filepath.Join(parentDir, "title.tik"), tmd.TitleID, titleKey, tmd.TitleVersion) - cert, err := wiiudownloader.GenerateCert(tmdData, contentCount, mw.progressWindow, http.DefaultClient) + cert, err := wiiudownloader.GenerateCert(tmd, mw.progressWindow, http.DefaultClient) if err != nil { return } diff --git a/decryption.go b/decryption.go index 399120d..e056508 100644 --- a/decryption.go +++ b/decryption.go @@ -416,7 +416,7 @@ func DecryptContents(path string, progressReporter ProgressReporter, deleteEncry if err != nil { return err } - tmd, err := parseTMD(tmdData) + tmd, err := ParseTMD(tmdData) if err != nil { return err } diff --git a/downloader.go b/downloader.go index 02703c6..e1f8345 100644 --- a/downloader.go +++ b/downloader.go @@ -184,7 +184,7 @@ func DownloadTitle(titleID, outputDirectory string, doDecryption bool, progressR return err } - tmd, err := parseTMD(tmdData) + tmd, err := ParseTMD(tmdData) if err != nil { return err } @@ -211,7 +211,7 @@ func DownloadTitle(titleID, outputDirectory string, doDecryption bool, progressR progressReporter.SetDownloadSize(int64(titleSize)) - cert, err := GenerateCert(tmdData, tmd.ContentCount, progressReporter, client) + cert, err := GenerateCert(tmd, progressReporter, client) if err != nil { if progressReporter.Cancelled() { return nil diff --git a/tmd.go b/tmd.go index 31b69ab..09bed25 100644 --- a/tmd.go +++ b/tmd.go @@ -18,9 +18,11 @@ type TMD struct { TitleVersion uint16 ContentCount uint16 Contents []Content + Certificate1 []byte + Certificate2 []byte } -func parseTMD(data []byte) (*TMD, error) { +func ParseTMD(data []byte) (*TMD, error) { tmd := &TMD{} reader := bytes.NewReader(data) @@ -75,6 +77,14 @@ func parseTMD(data []byte) (*TMD, error) { return nil, err } } + tmd.Certificate1 = make([]byte, 0x400) + if _, err := io.ReadFull(reader, tmd.Certificate1); err != nil { + return nil, err + } + tmd.Certificate2 = make([]byte, 0x300) + if _, err := io.ReadFull(reader, tmd.Certificate2); err != nil { + return nil, err + } case TMD_VERSION_WIIU: reader.Seek(0x18C, io.SeekStart) if err := binary.Read(reader, binary.BigEndian, &tmd.TitleID); err != nil { @@ -121,6 +131,14 @@ func parseTMD(data []byte) (*TMD, error) { return nil, err } } + tmd.Certificate1 = make([]byte, 0x400) + if _, err := io.ReadFull(reader, tmd.Certificate1); err != nil { + return nil, err + } + tmd.Certificate2 = make([]byte, 0x300) + if _, err := io.ReadFull(reader, tmd.Certificate2); err != nil { + return nil, err + } default: return nil, fmt.Errorf("unknown TMD version: %d", tmd.Version) }