IOS: Reuse IOSC instance when possible
Changes ESFormats to take an IOSC instance instead of creating its own temporary instance unnecessarily.
This commit is contained in:
parent
6d821de2b9
commit
9f08534a47
|
@ -380,7 +380,7 @@ u64 TicketReader::GetTitleId() const
|
||||||
return Common::swap64(m_bytes.data() + offsetof(Ticket, title_id));
|
return Common::swap64(m_bytes.data() + offsetof(Ticket, title_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, 16> TicketReader::GetTitleKey() const
|
std::array<u8, 16> TicketReader::GetTitleKey(const HLE::IOSC& iosc) const
|
||||||
{
|
{
|
||||||
u8 iv[16] = {};
|
u8 iv[16] = {};
|
||||||
std::copy_n(&m_bytes[offsetof(Ticket, title_id)], sizeof(Ticket::title_id), iv);
|
std::copy_n(&m_bytes[offsetof(Ticket, title_id)], sizeof(Ticket::title_id), iv);
|
||||||
|
@ -394,17 +394,20 @@ std::array<u8, 16> TicketReader::GetTitleKey() const
|
||||||
GetTitleId(), index);
|
GetTitleId(), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_rvt = (GetIssuer() == "Root-CA00000002-XS00000006");
|
|
||||||
const HLE::IOSC::ConsoleType console_type =
|
|
||||||
is_rvt ? HLE::IOSC::ConsoleType::RVT : HLE::IOSC::ConsoleType::Retail;
|
|
||||||
|
|
||||||
std::array<u8, 16> key;
|
std::array<u8, 16> key;
|
||||||
HLE::IOSC iosc(console_type);
|
|
||||||
iosc.Decrypt(common_key_handle, iv, &m_bytes[offsetof(Ticket, title_key)], 16, key.data(),
|
iosc.Decrypt(common_key_handle, iv, &m_bytes[offsetof(Ticket, title_key)], 16, key.data(),
|
||||||
HLE::PID_ES);
|
HLE::PID_ES);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<u8, 16> TicketReader::GetTitleKey() const
|
||||||
|
{
|
||||||
|
const bool is_rvt = (GetIssuer() == "Root-CA00000002-XS00000006");
|
||||||
|
const HLE::IOSC::ConsoleType console_type =
|
||||||
|
is_rvt ? HLE::IOSC::ConsoleType::RVT : HLE::IOSC::ConsoleType::Retail;
|
||||||
|
return GetTitleKey(HLE::IOSC{console_type});
|
||||||
|
}
|
||||||
|
|
||||||
void TicketReader::DeleteTicket(u64 ticket_id_to_delete)
|
void TicketReader::DeleteTicket(u64 ticket_id_to_delete)
|
||||||
{
|
{
|
||||||
std::vector<u8> new_ticket;
|
std::vector<u8> new_ticket;
|
||||||
|
@ -420,16 +423,16 @@ void TicketReader::DeleteTicket(u64 ticket_id_to_delete)
|
||||||
m_bytes = std::move(new_ticket);
|
m_bytes = std::move(new_ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 TicketReader::Unpersonalise()
|
HLE::ReturnCode TicketReader::Unpersonalise(HLE::IOSC& iosc)
|
||||||
{
|
{
|
||||||
const auto ticket_begin = m_bytes.begin();
|
const auto ticket_begin = m_bytes.begin();
|
||||||
|
|
||||||
// IOS uses IOSC to compute an AES key from the peer public key and the device's private ECC key,
|
// IOS uses IOSC to compute an AES key from the peer public key and the device's private ECC key,
|
||||||
// which is used the decrypt the title key. The IV is the ticket ID (8 bytes), zero extended.
|
// which is used the decrypt the title key. The IV is the ticket ID (8 bytes), zero extended.
|
||||||
using namespace HLE;
|
using namespace HLE;
|
||||||
IOSC iosc;
|
|
||||||
IOSC::Handle public_handle;
|
IOSC::Handle public_handle;
|
||||||
s32 ret = iosc.CreateObject(&public_handle, IOSC::TYPE_PUBLIC_KEY, IOSC::SUBTYPE_ECC233, PID_ES);
|
ReturnCode ret =
|
||||||
|
iosc.CreateObject(&public_handle, IOSC::TYPE_PUBLIC_KEY, IOSC::SUBTYPE_ECC233, PID_ES);
|
||||||
if (ret != IPC_SUCCESS)
|
if (ret != IPC_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,10 @@ public:
|
||||||
|
|
||||||
u32 GetDeviceId() const;
|
u32 GetDeviceId() const;
|
||||||
u64 GetTitleId() const;
|
u64 GetTitleId() const;
|
||||||
|
// Get the decrypted title key.
|
||||||
|
std::array<u8, 16> GetTitleKey(const HLE::IOSC& iosc) const;
|
||||||
|
// Same as the above version, but guesses the console type depending on the issuer
|
||||||
|
// and constructs a temporary IOSC instance.
|
||||||
std::array<u8, 16> GetTitleKey() const;
|
std::array<u8, 16> GetTitleKey() const;
|
||||||
|
|
||||||
// Deletes a ticket with the given ticket ID from the internal buffer.
|
// Deletes a ticket with the given ticket ID from the internal buffer.
|
||||||
|
@ -229,7 +233,7 @@ public:
|
||||||
|
|
||||||
// Decrypts the title key field for a "personalised" ticket -- one that is device-specific
|
// Decrypts the title key field for a "personalised" ticket -- one that is device-specific
|
||||||
// and has a title key that must be decrypted first.
|
// and has a title key that must be decrypted first.
|
||||||
s32 Unpersonalise();
|
HLE::ReturnCode Unpersonalise(HLE::IOSC& iosc);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SharedContentMap final
|
class SharedContentMap final
|
||||||
|
|
|
@ -60,7 +60,7 @@ ReturnCode ES::ImportTicket(const std::vector<u8>& ticket_bytes, const std::vect
|
||||||
WARN_LOG(IOS_ES, "Device ID mismatch: ticket %08x, device %08x", ticket_device_id, device_id);
|
WARN_LOG(IOS_ES, "Device ID mismatch: ticket %08x, device %08x", ticket_device_id, device_id);
|
||||||
return ES_DEVICE_ID_MISMATCH;
|
return ES_DEVICE_ID_MISMATCH;
|
||||||
}
|
}
|
||||||
const ReturnCode ret = static_cast<ReturnCode>(ticket.Unpersonalise());
|
const ReturnCode ret = ticket.Unpersonalise(m_ios.GetIOSC());
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG(IOS_ES, "ImportTicket: Failed to unpersonalise ticket for %016" PRIx64 " (%d)",
|
ERROR_LOG(IOS_ES, "ImportTicket: Failed to unpersonalise ticket for %016" PRIx64 " (%d)",
|
||||||
|
@ -294,8 +294,8 @@ ReturnCode ES::ImportContentEnd(Context& context, u32 content_fd)
|
||||||
u8 iv[16] = {0};
|
u8 iv[16] = {0};
|
||||||
iv[0] = (content_info.index >> 8) & 0xFF;
|
iv[0] = (content_info.index >> 8) & 0xFF;
|
||||||
iv[1] = content_info.index & 0xFF;
|
iv[1] = content_info.index & 0xFF;
|
||||||
std::vector<u8> decrypted_data = Common::AES::Decrypt(ticket.GetTitleKey().data(), iv,
|
std::vector<u8> decrypted_data = Common::AES::Decrypt(
|
||||||
context.title_import.content_buffer.data(),
|
ticket.GetTitleKey(m_ios.GetIOSC()).data(), iv, context.title_import.content_buffer.data(),
|
||||||
context.title_import.content_buffer.size());
|
context.title_import.content_buffer.size());
|
||||||
if (!CheckIfContentHashMatches(decrypted_data, content_info))
|
if (!CheckIfContentHashMatches(decrypted_data, content_info))
|
||||||
{
|
{
|
||||||
|
@ -570,7 +570,7 @@ ReturnCode ES::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u3
|
||||||
if (ticket.GetTitleId() != context.title_export.tmd.GetTitleId())
|
if (ticket.GetTitleId() != context.title_export.tmd.GetTitleId())
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
context.title_export.title_key = ticket.GetTitleKey();
|
context.title_export.title_key = ticket.GetTitleKey(m_ios.GetIOSC());
|
||||||
|
|
||||||
const std::vector<u8>& raw_tmd = context.title_export.tmd.GetBytes();
|
const std::vector<u8>& raw_tmd = context.title_export.tmd.GetBytes();
|
||||||
if (tmd_size != raw_tmd.size())
|
if (tmd_size != raw_tmd.size())
|
||||||
|
|
|
@ -117,7 +117,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(m_aes_key, ticket.GetTitleKey().data(), sizeof(m_aes_key));
|
memcpy(m_aes_key, ticket.GetTitleKey(m_ios.GetIOSC()).data(), sizeof(m_aes_key));
|
||||||
mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128);
|
mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue