Merge pull request #5646 from Starsam80/cert-import-fixes

NANDImporter: Improve certificate extraction
This commit is contained in:
shuffle2 2017-06-21 20:12:57 -07:00 committed by GitHub
commit f65fe3efbd
2 changed files with 60 additions and 25 deletions

View File

@ -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)

View File

@ -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)