diff --git a/Makefile b/Makefile index 4952464..a9f2bc9 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ DATA := data INCLUDES := include include/ui include/data include/install include/nx include/nx/ipc include/util $(CURDIR)/include/Plutonium/Plutonium/include APP_TITLE := TinWoo Installer APP_AUTHOR := MrDude -APP_VERSION := 1.0.19 +APP_VERSION := 1.0.20 ROMFS := romfs APP_ICON := icon.jpg diff --git a/include/install/install.hpp b/include/install/install.hpp index d1e1c99..24a4e32 100644 --- a/include/install/install.hpp +++ b/include/install/install.hpp @@ -54,13 +54,13 @@ namespace tin::install virtual void InstallContentMetaRecords(tin::data::ByteBuffer& installContentMetaBuf, int i); virtual void InstallApplicationRecord(int i); - virtual void InstallTicketCert() = 0; virtual void InstallNCA(const NcmContentId& ncaId) = 0; public: virtual ~Install(); virtual void Prepare(); + virtual void InstallTicketCert(); virtual void Begin(); virtual u64 GetTitleId(int i = 0); diff --git a/include/util/config.hpp b/include/util/config.hpp index e8ae277..4b8d759 100644 --- a/include/util/config.hpp +++ b/include/util/config.hpp @@ -5,7 +5,7 @@ namespace inst::config { static const std::string appDir = "sdmc:/switch/tinwoo"; static const std::string configPath = appDir + "/config.json"; - static const std::string appVersion = "1.0.19"; + static const std::string appVersion = "1.0.20"; extern std::string gAuthKey; extern std::string sigPatchesUrl; diff --git a/source/HDInstall.cpp b/source/HDInstall.cpp index 462a3ac..8cfff19 100644 --- a/source/HDInstall.cpp +++ b/source/HDInstall.cpp @@ -87,6 +87,7 @@ namespace nspInstStuff_B { inst::ui::instPage::setInstInfoText("inst.info_page.preparing"_lang); inst::ui::instPage::setInstBarPerc(0); installTask->Prepare(); + installTask->InstallTicketCert(); installTask->Begin(); togo = (togo - 1); } diff --git a/source/install/install.cpp b/source/install/install.cpp index 5bf1941..5659d92 100644 --- a/source/install/install.cpp +++ b/source/install/install.cpp @@ -160,16 +160,6 @@ namespace tin::install void Install::Begin() { - LOG_DEBUG("Installing ticket and cert...\n"); - try - { - this->InstallTicketCert(); - } - catch (std::runtime_error& e) - { - LOG_DEBUG("WARNING: Ticket installation failed! This may not be an issue, depending on your use case.\nProceed with caution!\n"); - } - for (nx::ncm::ContentMeta contentMeta : m_contentMeta) { LOG_DEBUG("Installing NCAs...\n"); for (auto& record : contentMeta.GetContentInfos()) @@ -180,6 +170,10 @@ namespace tin::install } } + void Install::InstallTicketCert() { + this->InstallTicketCert(); + } + u64 Install::GetTitleId(int i) { return m_contentMeta[i].GetContentMetaKey().id; diff --git a/source/install/install_nsp.cpp b/source/install/install_nsp.cpp index eb91faa..79cc9ce 100644 --- a/source/install/install_nsp.cpp +++ b/source/install/install_nsp.cpp @@ -75,7 +75,6 @@ namespace tin::install::nsp CNMTList.push_back({ tin::util::GetContentMetaFromNCA(cnmtNCAFullPath), cnmtContentInfo }); } - return CNMTList; } @@ -150,18 +149,9 @@ namespace tin::install::nsp void NSPInstall::InstallTicketCert() { - u16 ECDSA = 0; - u16 RSA_2048 = 0; - u16 RSA_4096 = 0; - // Read the tik files and put it into a buffer std::vector tikFileEntries = m_NSP->GetFileEntriesByExtension("tik"); std::vector certFileEntries = m_NSP->GetFileEntriesByExtension("cert"); - // https://switchbrew.org/wiki/Ticket#Certificate_chain - ECDSA = (0x4 + 0x3C + 0x40 + 0x146); - RSA_2048 = (0x4 + 0x100 + 0x3C + 0x146); - RSA_4096 = (0x4 + 0x200 + 0x3C + 0x146); - for (size_t i = 0; i < tikFileEntries.size(); i++) { if (tikFileEntries[i] == nullptr) { @@ -186,8 +176,16 @@ namespace tin::install::nsp m_NSP->BufferData(certBuf.get(), m_NSP->GetDataOffset() + certFileEntries[i]->dataOffset, certSize); // try to fix a temp ticket and change it t a permanent one + // https://switchbrew.org/wiki/Ticket#Certificate_chain if (inst::config::fixticket) { - //ECDSA SHA256 + u16 ECDSA = 0; + u16 RSA_2048 = 0; + u16 RSA_4096 = 0; + + ECDSA = (0x4 + 0x3C + 0x40 + 0x146); + RSA_2048 = (0x4 + 0x100 + 0x3C + 0x146); + RSA_4096 = (0x4 + 0x200 + 0x3C + 0x146); + if (tikBuf.get()[0x0] == 0x5 && (tikBuf.get()[ECDSA] == 0x10 || tikBuf.get()[ECDSA] == 0x30)) { tikBuf.get()[ECDSA] = 0x0; @@ -229,9 +227,7 @@ namespace tin::install::nsp tikBuf.get()[RSA_4096 - 1] = 0x10; } - } - - //printout the cert and ticket to a file in the tinwoo directory for testing. + //printout the cert and ticket to a file in the tinwoo directory for testing. /* FILE * pFile; pFile = fopen ("cert.hxd", "wb"); @@ -242,6 +238,7 @@ namespace tin::install::nsp fwrite (tikBuf.get(), sizeof(char), tikSize, pFile); fclose (pFile); */ + } // Finally, let's actually import the ticket ASSERT_OK(esImportTicket(tikBuf.get(), tikSize, certBuf.get(), certSize), "Failed to import ticket"); diff --git a/source/install/install_xci.cpp b/source/install/install_xci.cpp index e7dd1d7..f4fa930 100644 --- a/source/install/install_xci.cpp +++ b/source/install/install_xci.cpp @@ -145,21 +145,13 @@ namespace tin::install::xci catch (...) {} } + //xci files don't have a ticket or cert - so this is useful when installing a converted nsp to xci void XCIInstallTask::InstallTicketCert() { - u16 ECDSA = 0; - u16 RSA_2048 = 0; - u16 RSA_4096 = 0; - // Read the tik files and put it into a buffer std::vector tikFileEntries = m_xci->GetFileEntriesByExtension("tik"); std::vector certFileEntries = m_xci->GetFileEntriesByExtension("cert"); - // https://switchbrew.org/wiki/Ticket#Certificate_chain - ECDSA = (0x4 + 0x3C + 0x40 + 0x146); - RSA_2048 = (0x4 + 0x100 + 0x3C + 0x146); - RSA_4096 = (0x4 + 0x200 + 0x3C + 0x146); - for (size_t i = 0; i < tikFileEntries.size(); i++) { if (tikFileEntries[i] == nullptr) @@ -186,6 +178,15 @@ namespace tin::install::xci // try to fix a temp ticket and change it t a permanent one if (inst::config::fixticket) { + u16 ECDSA = 0; + u16 RSA_2048 = 0; + u16 RSA_4096 = 0; + + // https://switchbrew.org/wiki/Ticket#Certificate_chain + ECDSA = (0x4 + 0x3C + 0x40 + 0x146); + RSA_2048 = (0x4 + 0x100 + 0x3C + 0x146); + RSA_4096 = (0x4 + 0x200 + 0x3C + 0x146); + //ECDSA SHA256 if (tikBuf.get()[0x0] == 0x5 && (tikBuf.get()[ECDSA] == 0x10 || tikBuf.get()[ECDSA] == 0x30)) { diff --git a/source/install/nsp.cpp b/source/install/nsp.cpp index b40ecee..649efc8 100644 --- a/source/install/nsp.cpp +++ b/source/install/nsp.cpp @@ -69,15 +69,6 @@ namespace tin::install::nsp size_t fileEntryOffset = sizeof(PFS0BaseHeader) + index * sizeof(PFS0FileEntry); - /* - //print fileEntryOffset - FILE * fp; - fp = fopen ("offset.txt", "a+"); - size_t debug = fileEntryOffset; - fprintf(fp, "%zu\n", debug); - fclose(fp); - */ - if (m_headerBytes.size() < fileEntryOffset + sizeof(PFS0FileEntry)) THROW_FORMAT("Header bytes is too small to get file entry!"); @@ -92,7 +83,15 @@ namespace tin::install::nsp { const PFS0FileEntry* fileEntry = this->GetFileEntry(i); std::string name(this->GetFileEntryName(fileEntry)); - auto foundExtension = name.substr(name.find(".") + 1); + + // fix cert filname extension becoming corrupted when xcz/nsz is installing certs/ticks. + FILE* fp; + int pos = 0; + std::string mystr = name; + pos = mystr.find_last_of('.'); + mystr = mystr.substr(5, pos); + //auto foundExtension = name.substr(name.find(".") + 1); + auto foundExtension = mystr.substr(mystr.find(".") + 1); if (foundExtension == extension) entryList.push_back(fileEntry); @@ -103,13 +102,26 @@ namespace tin::install::nsp const PFS0FileEntry* NSP::GetFileEntryByName(std::string name) { + //returns only the .nca and .cnmt.nca filenames for (unsigned int i = 0; i < this->GetBaseHeader()->numFiles; i++) { const PFS0FileEntry* fileEntry = this->GetFileEntry(i); std::string foundName(this->GetFileEntryName(fileEntry)); - if (foundName == name) + + if (foundName == name) { + /* + //Debug code + FILE * fp; + fp = fopen ("name.txt", "a+"); + std::string x = foundName; + const char *info = x.c_str(); + fprintf(fp, "%s\n", info); + fclose(fp); + */ + return fileEntry; + } } return nullptr; @@ -140,6 +152,17 @@ namespace tin::install::nsp const char* NSP::GetFileEntryName(const PFS0FileEntry* fileEntry) { u64 stringTableStart = sizeof(PFS0BaseHeader) + this->GetBaseHeader()->numFiles * sizeof(PFS0FileEntry); + + //check for messed up filenames in our table.... usually when instaling xcz/xci + /* + FILE * fp; + fp = fopen ("st.txt", "a+"); + std::string x = reinterpret_cast(m_headerBytes.data() + stringTableStart + fileEntry->stringTableOffset); + const char *info = x.c_str(); + fprintf(fp, "%s\n", info); + fclose(fp); + */ + return reinterpret_cast(m_headerBytes.data() + stringTableStart + fileEntry->stringTableOffset); } @@ -155,16 +178,6 @@ namespace tin::install::nsp { if (m_headerBytes.empty()) THROW_FORMAT("Cannot get data offset as header is empty. Have you retrieved it yet?\n"); - - /* - //print size of header - FILE * fp; - fp = fopen ("file.txt", "a+"); - u64 debug = m_headerBytes.size(); - fprintf(fp, "%lu\n", debug); - fclose(fp); - */ - return m_headerBytes.size(); } } \ No newline at end of file diff --git a/source/install/xci.cpp b/source/install/xci.cpp index 2756b79..ab2ba43 100644 --- a/source/install/xci.cpp +++ b/source/install/xci.cpp @@ -158,7 +158,15 @@ namespace tin::install::xci { const HFS0FileEntry* fileEntry = this->GetFileEntry(i); std::string name(this->GetFileEntryName(fileEntry)); - auto foundExtension = name.substr(name.find(".") + 1); + + // fix cert filname extension becoming corrupted when xcz/nsz is installing certs/ticks. + FILE* fp; + int pos = 0; + std::string mystr = name; + pos = mystr.find_last_of('.'); + mystr = mystr.substr(5, pos); + //auto foundExtension = name.substr(name.find(".") + 1); + auto foundExtension = mystr.substr(mystr.find(".") + 1); if (foundExtension == extension) entryList.push_back(fileEntry); diff --git a/source/netInstall.cpp b/source/netInstall.cpp index 416a23b..2d9f559 100644 --- a/source/netInstall.cpp +++ b/source/netInstall.cpp @@ -228,6 +228,7 @@ namespace netInstStuff { inst::ui::instPage::setInstInfoText("inst.info_page.preparing"_lang); inst::ui::instPage::setInstBarPerc(0); installTask->Prepare(); + installTask->InstallTicketCert(); installTask->Begin(); togo = (togo - 1); } @@ -398,10 +399,10 @@ namespace netInstStuff { //If the above fails we probably have an html page - try to download it instead. if (response.empty()) { response = inst::curl::html_to_buffer(url); - if (response.empty()) { - inst::ui::mainApp->CreateShowDialog("inst.net.index_error"_lang, "inst.net.index_error_info"_lang, { "common.ok"_lang }, true, "romfs:/images/icons/fail.png"); - break; - } + if (response.empty()) { + inst::ui::mainApp->CreateShowDialog("inst.net.index_error"_lang, "inst.net.index_error_info"_lang, { "common.ok"_lang }, true, "romfs:/images/icons/fail.png"); + break; + } } } @@ -441,7 +442,7 @@ namespace netInstStuff { defined in the settings page */ if (!inst::config::listoveride && nowlist >= maxlist) { - break; + break; } else { if (link.find("http") == std::string::npos) { diff --git a/source/nx/nca_writer.cpp b/source/nx/nca_writer.cpp index 0105b07..74ac95d 100644 --- a/source/nx/nca_writer.cpp +++ b/source/nx/nca_writer.cpp @@ -101,6 +101,8 @@ public: class SectionContext : public Section { public: + Crypto::Aes128Ctr crypto; + SectionContext(const Section& s) : Section(s), crypto(s.cryptoKey, Crypto::AesCtr(Crypto::swapEndian(((u64*)&s.cryptoCounter)[0]))) { } @@ -111,27 +113,27 @@ public: void decrypt(void* p, u64 sz, u64 offset) { - if (this->cryptoType != 3) + if (this->cryptoType == 3 || this->cryptoType == 4) { + crypto.seek(offset); + crypto.decrypt(p, p, sz); + } + else { return; } - - crypto.seek(offset); - crypto.decrypt(p, p, sz); } void encrypt(void* p, u64 sz, u64 offset) { - if (this->cryptoType != 3) + if (this->cryptoType == 3 || this->cryptoType == 4) { + crypto.seek(offset); + crypto.encrypt(p, p, sz); + } + else { return; } - - crypto.seek(offset); - crypto.encrypt(p, p, sz); } - - Crypto::Aes128Ctr crypto; }; const bool isValid() diff --git a/source/sdInstall.cpp b/source/sdInstall.cpp index fea620d..dd280fc 100644 --- a/source/sdInstall.cpp +++ b/source/sdInstall.cpp @@ -87,7 +87,8 @@ namespace nspInstStuff { inst::ui::instPage::setInstInfoText("inst.info_page.preparing"_lang); inst::ui::instPage::setInstBarPerc(0); installTask->Prepare(); - installTask->Begin(); + installTask->InstallTicketCert(); + installTask->Begin(); //install nca files togo = (togo - 1); } diff --git a/source/usbInstall.cpp b/source/usbInstall.cpp index b211219..5888a5b 100644 --- a/source/usbInstall.cpp +++ b/source/usbInstall.cpp @@ -137,6 +137,7 @@ namespace usbInstStuff { inst::ui::instPage::setInstInfoText("inst.info_page.preparing"_lang); inst::ui::instPage::setInstBarPerc(0); installTask->Prepare(); + installTask->InstallTicketCert(); installTask->Begin(); togo = (togo - 1); }