Skip to content

Commit

Permalink
Merge pull request #5646 from Starsam80/cert-import-fixes
Browse files Browse the repository at this point in the history
NANDImporter: Improve certificate extraction
  • Loading branch information
shuffle2 committed Jun 22, 2017
2 parents 4d0dd93 + 5399311 commit f65fe3e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 24 deletions.
81 changes: 58 additions & 23 deletions Source/Core/DiscIO/NANDImporter.cpp
Expand Up @@ -4,6 +4,7 @@

#include "DiscIO/NANDImporter.h"

#include <algorithm>
#include <array>
#include <cinttypes>
#include <cstring>
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

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

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)
{
file.Seek(cert.offset, SEEK_SET);
std::vector<u8> pem_cert(cert.size);
file.ReadBytes(pem_cert.data(), pem_cert.size());
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);

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());
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)
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DiscIO/NANDImporter.h
Expand Up @@ -19,7 +19,7 @@ class NANDImporter final
~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)
Expand Down

0 comments on commit f65fe3e

Please sign in to comment.