IOS/ESFormats: Use SignedBlobReader for TMDs and tickets

This commit is contained in:
Léo Lam 2017-06-11 13:24:45 +02:00
parent 2ec04675c9
commit 6c3069be97
10 changed files with 24 additions and 86 deletions

View File

@ -110,7 +110,7 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request)
// Read TMD to the buffer
const IOS::ES::TMDReader tmd = DVDThread::GetTMD(partition);
const std::vector<u8> raw_tmd = tmd.GetRawTMD();
const std::vector<u8>& raw_tmd = tmd.GetBytes();
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
ES::DIVerify(tmd, DVDThread::GetTicket(partition));

View File

@ -610,7 +610,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
if (!File::Exists(tmd_path))
{
File::IOFile tmd_file(tmd_path, "wb");
const std::vector<u8>& tmd_bytes = tmd.GetRawTMD();
const std::vector<u8>& tmd_bytes = tmd.GetBytes();
if (!tmd_file.WriteBytes(tmd_bytes.data(), tmd_bytes.size()))
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
}

View File

@ -164,26 +164,19 @@ bool IsValidTMDSize(size_t size)
return size <= 0x49e4;
}
TMDReader::TMDReader(const std::vector<u8>& bytes) : m_bytes(bytes)
TMDReader::TMDReader(const std::vector<u8>& bytes) : SignedBlobReader(bytes)
{
}
TMDReader::TMDReader(std::vector<u8>&& bytes) : m_bytes(std::move(bytes))
TMDReader::TMDReader(std::vector<u8>&& bytes) : SignedBlobReader(std::move(bytes))
{
}
void TMDReader::SetBytes(const std::vector<u8>& bytes)
{
m_bytes = bytes;
}
void TMDReader::SetBytes(std::vector<u8>&& bytes)
{
m_bytes = std::move(bytes);
}
bool TMDReader::IsValid() const
{
if (!IsSignatureValid())
return false;
if (m_bytes.size() < sizeof(TMDHeader))
{
// TMD is too small to contain its base fields.
@ -199,11 +192,6 @@ bool TMDReader::IsValid() const
return true;
}
const std::vector<u8>& TMDReader::GetRawTMD() const
{
return m_bytes;
}
std::vector<u8> TMDReader::GetRawHeader() const
{
return std::vector<u8>(m_bytes.begin(), m_bytes.begin() + sizeof(TMDHeader));
@ -331,37 +319,17 @@ bool TMDReader::FindContentById(u32 id, Content* content) const
return false;
}
void TMDReader::DoState(PointerWrap& p)
{
p.Do(m_bytes);
}
TicketReader::TicketReader(const std::vector<u8>& bytes) : m_bytes(bytes)
TicketReader::TicketReader(const std::vector<u8>& bytes) : SignedBlobReader(bytes)
{
}
TicketReader::TicketReader(std::vector<u8>&& bytes) : m_bytes(std::move(bytes))
TicketReader::TicketReader(std::vector<u8>&& bytes) : SignedBlobReader(std::move(bytes))
{
}
void TicketReader::SetBytes(const std::vector<u8>& bytes)
{
m_bytes = bytes;
}
void TicketReader::SetBytes(std::vector<u8>&& bytes)
{
m_bytes = std::move(bytes);
}
bool TicketReader::IsValid() const
{
return !m_bytes.empty() && m_bytes.size() % sizeof(Ticket) == 0;
}
void TicketReader::DoState(PointerWrap& p)
{
p.Do(m_bytes);
return IsSignatureValid() && !m_bytes.empty() && m_bytes.size() % sizeof(Ticket) == 0;
}
size_t TicketReader::GetNumberOfTickets() const
@ -369,11 +337,6 @@ size_t TicketReader::GetNumberOfTickets() const
return m_bytes.size() / sizeof(Ticket);
}
const std::vector<u8>& TicketReader::GetRawTicket() const
{
return m_bytes;
}
std::vector<u8> TicketReader::GetRawTicket(u64 ticket_id_to_find) const
{
for (size_t i = 0; i < GetNumberOfTickets(); ++i)
@ -404,13 +367,6 @@ std::vector<u8> TicketReader::GetRawTicketView(u32 ticket_num) const
return view;
}
std::string TicketReader::GetIssuer() const
{
const char* bytes =
reinterpret_cast<const char*>(m_bytes.data() + offsetof(Ticket, signature.issuer));
return std::string(bytes, strnlen(bytes, sizeof(Ticket::signature.issuer)));
}
u32 TicketReader::GetDeviceId() const
{
return Common::swap32(m_bytes.data() + offsetof(Ticket, device_id));

View File

@ -169,20 +169,16 @@ protected:
bool IsValidTMDSize(size_t size);
class TMDReader final
class TMDReader final : public SignedBlobReader
{
public:
TMDReader() = default;
explicit TMDReader(const std::vector<u8>& bytes);
explicit TMDReader(std::vector<u8>&& bytes);
void SetBytes(const std::vector<u8>& bytes);
void SetBytes(std::vector<u8>&& bytes);
bool IsValid() const;
// Returns the TMD or parts of it without any kind of parsing. Intended for use by ES.
const std::vector<u8>& GetRawTMD() const;
// Returns parts of the TMD without any kind of parsing. Intended for use by ES.
std::vector<u8> GetRawHeader() const;
std::vector<u8> GetRawView() const;
@ -203,27 +199,17 @@ public:
bool GetContent(u16 index, Content* content) const;
std::vector<Content> GetContents() const;
bool FindContentById(u32 id, Content* content) const;
void DoState(PointerWrap& p);
private:
std::vector<u8> m_bytes;
};
class TicketReader final
class TicketReader final : public SignedBlobReader
{
public:
TicketReader() = default;
explicit TicketReader(const std::vector<u8>& bytes);
explicit TicketReader(std::vector<u8>&& bytes);
void SetBytes(const std::vector<u8>& bytes);
void SetBytes(std::vector<u8>&& bytes);
bool IsValid() const;
void DoState(PointerWrap& p);
const std::vector<u8>& GetRawTicket() const;
std::vector<u8> GetRawTicket(u64 ticket_id) const;
size_t GetNumberOfTickets() const;
@ -233,7 +219,6 @@ public:
// more than just one ticket and generate ticket views for them, so we implement it too.
std::vector<u8> GetRawTicketView(u32 ticket_num) const;
std::string GetIssuer() const;
u32 GetDeviceId() const;
u64 GetTitleId() const;
std::vector<u8> GetTitleKey() const;
@ -244,9 +229,6 @@ public:
// Decrypts the title key field for a "personalised" ticket -- one that is device-specific
// and has a title key that must be decrypted first.
s32 Unpersonalise();
private:
std::vector<u8> m_bytes;
};
class SharedContentMap final

View File

@ -254,7 +254,7 @@ bool ES::WriteImportTMD(const IOS::ES::TMDReader& tmd)
{
File::IOFile file(tmd_path, "wb");
if (!file.WriteBytes(tmd.GetRawTMD().data(), tmd.GetRawTMD().size()))
if (!file.WriteBytes(tmd.GetBytes().data(), tmd.GetBytes().size()))
return false;
}

View File

@ -150,7 +150,7 @@ IPCCommandResult ES::GetStoredTMDSize(const IOCtlVRequest& request)
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
const u32 tmd_size = static_cast<u32>(tmd.GetRawTMD().size());
const u32 tmd_size = static_cast<u32>(tmd.GetBytes().size());
Memory::Write_U32(tmd_size, request.io_vectors[0].address);
INFO_LOG(IOS_ES, "GetStoredTMDSize: %u bytes for %016" PRIx64, tmd_size, title_id);
@ -171,7 +171,7 @@ IPCCommandResult ES::GetStoredTMD(const IOCtlVRequest& request)
// TODO: actually use this param in when writing to the outbuffer :/
const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
const std::vector<u8> raw_tmd = tmd.GetRawTMD();
const std::vector<u8>& raw_tmd = tmd.GetBytes();
if (raw_tmd.size() != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);

View File

@ -40,7 +40,7 @@ static ReturnCode WriteTicket(const IOS::ES::TicketReader& ticket)
if (!ticket_file)
return ES_EIO;
const std::vector<u8>& raw_ticket = ticket.GetRawTicket();
const std::vector<u8>& raw_ticket = ticket.GetBytes();
return ticket_file.WriteBytes(raw_ticket.data(), raw_ticket.size()) ? IPC_SUCCESS : ES_EIO;
}
@ -394,7 +394,7 @@ ReturnCode ES::DeleteTicket(const u8* ticket_view)
const u64 ticket_id = Common::swap64(ticket_view + offsetof(IOS::ES::TicketView, ticket_id));
ticket.DeleteTicket(ticket_id);
const std::vector<u8>& new_ticket = ticket.GetRawTicket();
const std::vector<u8>& new_ticket = ticket.GetBytes();
const std::string ticket_path = Common::GetTicketFileName(title_id, Common::FROM_SESSION_ROOT);
{
File::IOFile ticket_file(ticket_path, "wb");
@ -505,7 +505,7 @@ ReturnCode ES::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u3
context.title_export.title_key = ticket.GetTitleKey();
const auto& raw_tmd = context.title_export.tmd.GetRawTMD();
const std::vector<u8>& raw_tmd = context.title_export.tmd.GetBytes();
if (tmd_size != raw_tmd.size())
return ES_EINVAL;

View File

@ -376,7 +376,7 @@ IPCCommandResult ES::DIGetTMDSize(const IOCtlVRequest& request)
if (!GetTitleContext().active)
return GetDefaultReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(GetTitleContext().tmd.GetRawTMD().size()),
Memory::Write_U32(static_cast<u32>(GetTitleContext().tmd.GetBytes().size()),
request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
}
@ -393,7 +393,7 @@ IPCCommandResult ES::DIGetTMD(const IOCtlVRequest& request)
if (!GetTitleContext().active)
return GetDefaultReply(ES_EINVAL);
const std::vector<u8>& tmd_bytes = GetTitleContext().tmd.GetRawTMD();
const std::vector<u8>& tmd_bytes = GetTitleContext().tmd.GetBytes();
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
return GetDefaultReply(ES_EINVAL);

View File

@ -27,8 +27,8 @@ bool InstallWAD(const std::string& wad_path)
const auto es = ios.GetES();
IOS::HLE::Device::ES::Context context;
if (es->ImportTicket(wad.GetTicket().GetRawTicket()) < 0 ||
es->ImportTitleInit(context, tmd.GetRawTMD()) < 0)
if (es->ImportTicket(wad.GetTicket().GetBytes()) < 0 ||
es->ImportTitleInit(context, tmd.GetBytes()) < 0)
{
PanicAlertT("WAD installation failed: Could not initialise title import.");
return false;

View File

@ -76,7 +76,7 @@ void TMDReaderTest::TestGeneralInfo()
void TMDReaderTest::TestRawTMDAndView()
{
const std::vector<u8>& dolphin_tmd_bytes = m_tmd.GetRawTMD();
const std::vector<u8>& dolphin_tmd_bytes = m_tmd.GetBytes();
// Separate check because gtest prints neither the size nor the full buffer.
EXPECT_EQ(m_raw_tmd.size(), dolphin_tmd_bytes.size());
EXPECT_EQ(m_raw_tmd, dolphin_tmd_bytes);