Merge pull request #5130 from B3n30/warn_if_cia_contend_is_encrypted
Show an error if CIA contend is encrypted
This commit is contained in:
commit
026a63bcf7
|
@ -46,13 +46,15 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
|
||||||
const bool is_dir = FileUtil::IsDirectory(physical_name);
|
const bool is_dir = FileUtil::IsDirectory(physical_name);
|
||||||
if (!is_dir && HasSupportedFileExtension(physical_name)) {
|
if (!is_dir && HasSupportedFileExtension(physical_name)) {
|
||||||
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name);
|
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name);
|
||||||
if (!loader)
|
if (!loader) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool executable = false;
|
bool executable = false;
|
||||||
loader->IsExecutable(executable);
|
const auto res = loader->IsExecutable(executable);
|
||||||
if (!executable)
|
if (!executable && res != Loader::ResultStatus::ErrorEncrypted) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
u64 program_id = 0;
|
u64 program_id = 0;
|
||||||
loader->ReadProgramId(program_id);
|
loader->ReadProgramId(program_id);
|
||||||
|
|
|
@ -133,8 +133,39 @@ Loader::ResultStatus NCCHContainer::OpenFile(const std::string& filepath, u32 nc
|
||||||
return Loader::ResultStatus::Success;
|
return Loader::ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader::ResultStatus NCCHContainer::LoadHeader() {
|
||||||
|
if (has_header) {
|
||||||
|
return Loader::ResultStatus::Success;
|
||||||
|
}
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
return Loader::ResultStatus::Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset read pointer in case this file has been read before.
|
||||||
|
file.Seek(ncch_offset, SEEK_SET);
|
||||||
|
|
||||||
|
if (file.ReadBytes(&ncch_header, sizeof(NCCH_Header)) != sizeof(NCCH_Header)) {
|
||||||
|
return Loader::ResultStatus::Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
|
||||||
|
if (Loader::MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) {
|
||||||
|
LOG_DEBUG(Service_FS, "Only loading the first (bootable) NCCH within the NCSD file!");
|
||||||
|
ncch_offset += 0x4000;
|
||||||
|
file.Seek(ncch_offset, SEEK_SET);
|
||||||
|
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we are loading the correct file type...
|
||||||
|
if (Loader::MakeMagic('N', 'C', 'C', 'H') != ncch_header.magic) {
|
||||||
|
return Loader::ResultStatus::ErrorInvalidFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_header = true;
|
||||||
|
return Loader::ResultStatus::Success;
|
||||||
|
}
|
||||||
|
|
||||||
Loader::ResultStatus NCCHContainer::Load() {
|
Loader::ResultStatus NCCHContainer::Load() {
|
||||||
LOG_INFO(Service_FS, "Loading NCCH from file {}", filepath);
|
|
||||||
if (is_loaded)
|
if (is_loaded)
|
||||||
return Loader::ResultStatus::Success;
|
return Loader::ResultStatus::Success;
|
||||||
|
|
||||||
|
@ -697,7 +728,7 @@ Loader::ResultStatus NCCHContainer::ReadOverrideRomFS(std::shared_ptr<RomFSReade
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader::ResultStatus NCCHContainer::ReadProgramId(u64_le& program_id) {
|
Loader::ResultStatus NCCHContainer::ReadProgramId(u64_le& program_id) {
|
||||||
Loader::ResultStatus result = Load();
|
Loader::ResultStatus result = LoadHeader();
|
||||||
if (result != Loader::ResultStatus::Success)
|
if (result != Loader::ResultStatus::Success)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,12 @@ public:
|
||||||
|
|
||||||
Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0);
|
Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure NCCH header is loaded and ready for reading sections
|
||||||
|
* @return ResultStatus result of function
|
||||||
|
*/
|
||||||
|
Loader::ResultStatus LoadHeader();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure ExeFS and exheader is loaded and ready for reading sections
|
* Ensure ExeFS and exheader is loaded and ready for reading sections
|
||||||
* @return ResultStatus result of function
|
* @return ResultStatus result of function
|
||||||
|
|
|
@ -47,6 +47,7 @@ std::optional<std::array<u8, 16>> Ticket::GetTitleKey() const {
|
||||||
std::memcpy(ctr.data(), &ticket_body.title_id, sizeof(u64));
|
std::memcpy(ctr.data(), &ticket_body.title_id, sizeof(u64));
|
||||||
HW::AES::SelectCommonKeyIndex(ticket_body.common_key_index);
|
HW::AES::SelectCommonKeyIndex(ticket_body.common_key_index);
|
||||||
if (!HW::AES::IsNormalKeyAvailable(HW::AES::KeySlotID::TicketCommonKey)) {
|
if (!HW::AES::IsNormalKeyAvailable(HW::AES::KeySlotID::TicketCommonKey)) {
|
||||||
|
LOG_ERROR(Service_FS, "CommonKey {} missing", ticket_body.common_key_index);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto key = HW::AES::GetNormalKey(HW::AES::KeySlotID::TicketCommonKey);
|
auto key = HW::AES::GetNormalKey(HW::AES::KeySlotID::TicketCommonKey);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <cryptopp/aes.h>
|
#include <cryptopp/aes.h>
|
||||||
#include <cryptopp/modes.h>
|
#include <cryptopp/modes.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include "common/common_paths.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
@ -373,6 +374,37 @@ InstallStatus InstallCIA(const std::string& path,
|
||||||
installFile.Close();
|
installFile.Close();
|
||||||
|
|
||||||
LOG_INFO(Service_AM, "Installed {} successfully.", path);
|
LOG_INFO(Service_AM, "Installed {} successfully.", path);
|
||||||
|
|
||||||
|
const FileUtil::DirectoryEntryCallable callback =
|
||||||
|
[&callback](u64* num_entries_out, const std::string& directory,
|
||||||
|
const std::string& virtual_name) -> bool {
|
||||||
|
const std::string physical_name = directory + DIR_SEP + virtual_name;
|
||||||
|
const bool is_dir = FileUtil::IsDirectory(physical_name);
|
||||||
|
if (!is_dir) {
|
||||||
|
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name);
|
||||||
|
if (!loader) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool executable = false;
|
||||||
|
const auto res = loader->IsExecutable(executable);
|
||||||
|
if (res == Loader::ResultStatus::ErrorEncrypted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return FileUtil::ForeachDirectoryEntry(nullptr, physical_name, callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!FileUtil::ForeachDirectoryEntry(
|
||||||
|
nullptr,
|
||||||
|
GetTitlePath(
|
||||||
|
Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID()),
|
||||||
|
container.GetTitleMetadata().GetTitleID()),
|
||||||
|
callback)) {
|
||||||
|
LOG_ERROR(Service_AM, "CIA {} contained encrypted files.", path);
|
||||||
|
return InstallStatus::ErrorEncrypted;
|
||||||
|
}
|
||||||
return InstallStatus::Success;
|
return InstallStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue