Merge pull request #5646 from Starsam80/cert-import-fixes
NANDImporter: Improve certificate extraction
This commit is contained in:
commit
f65fe3efbd
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "DiscIO/NANDImporter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
|
@ -15,6 +16,7 @@
|
|||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
|
||||
namespace DiscIO
|
||||
|
@ -188,40 +190,73 @@ void NANDImporter::ProcessFile(const NANDFSTEntry& entry, const std::string& par
|
|||
}
|
||||
}
|
||||
|
||||
void NANDImporter::ExtractCertificates(const std::string& nand_root)
|
||||
bool NANDImporter::ExtractCertificates(const std::string& nand_root)
|
||||
{
|
||||
const std::string title_contents_path =
|
||||
nand_root + "/title/00000001/0000000d/content/00000011.app";
|
||||
File::IOFile file(title_contents_path, "rb");
|
||||
if (!file)
|
||||
const std::string content_dir = nand_root + "/title/00000001/0000000d/content/";
|
||||
|
||||
File::IOFile tmd_file(content_dir + "title.tmd", "rb");
|
||||
std::vector<u8> tmd_bytes(tmd_file.GetSize());
|
||||
if (!tmd_file.ReadBytes(tmd_bytes.data(), tmd_bytes.size()))
|
||||
{
|
||||
PanicAlertT("Unable to open %s! Refer to "
|
||||
"https://dolphin-emu.org/docs/guides/wii-network-guide/ to set up "
|
||||
"certificates.",
|
||||
title_contents_path.c_str());
|
||||
return;
|
||||
ERROR_LOG(DISCIO, "ExtractCertificates: Could not read IOS13 TMD");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Certificate
|
||||
IOS::ES::TMDReader tmd(std::move(tmd_bytes));
|
||||
IOS::ES::Content content_metadata;
|
||||
if (!tmd.GetContent(tmd.GetBootIndex(), &content_metadata))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "ExtractCertificates: Could not get content ID from TMD");
|
||||
return false;
|
||||
}
|
||||
|
||||
File::IOFile content_file(content_dir + StringFromFormat("%08x.app", content_metadata.id), "rb");
|
||||
std::vector<u8> content_bytes(content_file.GetSize());
|
||||
if (!content_file.ReadBytes(content_bytes.data(), content_bytes.size()))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "ExtractCertificates: Could not read IOS13 contents");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct PEMCertificate
|
||||
{
|
||||
u32 offset;
|
||||
u32 size;
|
||||
std::string filename;
|
||||
std::array<u8, 4> search_bytes;
|
||||
};
|
||||
std::array<Certificate, 3> certificates = {{{0x92834, 1005, "/clientca.pem"},
|
||||
{0x92d38, 609, "/clientcakey.pem"},
|
||||
{0x92440, 897, "/rootca.pem"}}};
|
||||
for (const Certificate& cert : certificates)
|
||||
{
|
||||
file.Seek(cert.offset, SEEK_SET);
|
||||
std::vector<u8> pem_cert(cert.size);
|
||||
file.ReadBytes(pem_cert.data(), pem_cert.size());
|
||||
|
||||
const std::string pem_file_path = nand_root + cert.filename;
|
||||
File::IOFile pem_file(pem_file_path, "wb");
|
||||
if (!pem_file.WriteBytes(pem_cert.data(), pem_cert.size()))
|
||||
PanicAlertT("Unable to write to file %s", pem_file_path.c_str());
|
||||
std::array<PEMCertificate, 3> certificates = {{
|
||||
{"/clientca.pem", {{0x30, 0x82, 0x03, 0xE9}}},
|
||||
{"/clientcakey.pem", {{0x30, 0x82, 0x02, 0x5D}}},
|
||||
{"/rootca.pem", {{0x30, 0x82, 0x03, 0x7D}}},
|
||||
}};
|
||||
|
||||
for (const PEMCertificate& certificate : certificates)
|
||||
{
|
||||
const auto search_result =
|
||||
std::search(content_bytes.begin(), content_bytes.end(), certificate.search_bytes.begin(),
|
||||
certificate.search_bytes.end());
|
||||
|
||||
if (search_result == content_bytes.end())
|
||||
{
|
||||
ERROR_LOG(DISCIO, "ExtractCertificates: Could not find offset for certficate '%s'",
|
||||
certificate.filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string pem_file_path = nand_root + certificate.filename;
|
||||
const ptrdiff_t certificate_offset = std::distance(content_bytes.begin(), search_result);
|
||||
const u16 certificate_size = Common::swap16(&content_bytes[certificate_offset - 2]);
|
||||
INFO_LOG(DISCIO, "ExtractCertificates: '%s' offset: 0x%tx size: 0x%x",
|
||||
certificate.filename.c_str(), certificate_offset, certificate_size);
|
||||
|
||||
File::IOFile pem_file(pem_file_path, "wb");
|
||||
if (!pem_file.WriteBytes(&content_bytes[certificate_offset], certificate_size))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "ExtractCertificates: Unable to write to file %s", pem_file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NANDImporter::ExportKeys(const std::string& nand_root)
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
~NANDImporter();
|
||||
|
||||
void ImportNANDBin(const std::string& path_to_bin, std::function<void()> update_callback);
|
||||
void ExtractCertificates(const std::string& nand_root);
|
||||
bool ExtractCertificates(const std::string& nand_root);
|
||||
|
||||
private:
|
||||
#pragma pack(push, 1)
|
||||
|
|
Loading…
Reference in New Issue