mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 21:35:28 +00:00
VolumeWiiCrypted: Cache TMDs and tickets
This commit is contained in:
parent
a0e4bb4aa6
commit
5c68a03ae4
@ -32,6 +32,9 @@ static const unsigned int WII_BANNER_HEIGHT = 64;
|
|||||||
static const unsigned int WII_BANNER_SIZE = WII_BANNER_WIDTH * WII_BANNER_HEIGHT * 2;
|
static const unsigned int WII_BANNER_SIZE = WII_BANNER_WIDTH * WII_BANNER_HEIGHT * 2;
|
||||||
static const unsigned int WII_BANNER_OFFSET = 0xA0;
|
static const unsigned int WII_BANNER_OFFSET = 0xA0;
|
||||||
|
|
||||||
|
const IOS::ES::TicketReader IVolume::INVALID_TICKET{};
|
||||||
|
const IOS::ES::TMDReader IVolume::INVALID_TMD{};
|
||||||
|
|
||||||
std::vector<u32> IVolume::GetWiiBanner(int* width, int* height, u64 title_id)
|
std::vector<u32> IVolume::GetWiiBanner(int* width, int* height, u64 title_id)
|
||||||
{
|
{
|
||||||
*width = 0;
|
*width = 0;
|
||||||
|
@ -55,8 +55,11 @@ public:
|
|||||||
virtual Partition GetGamePartition() const { return PARTITION_NONE; }
|
virtual Partition GetGamePartition() const { return PARTITION_NONE; }
|
||||||
bool GetTitleID(u64* buffer) const { return GetTitleID(buffer, GetGamePartition()); }
|
bool GetTitleID(u64* buffer) const { return GetTitleID(buffer, GetGamePartition()); }
|
||||||
virtual bool GetTitleID(u64* buffer, const Partition& partition) const { return false; }
|
virtual bool GetTitleID(u64* buffer, const Partition& partition) const { return false; }
|
||||||
virtual IOS::ES::TicketReader GetTicket(const Partition& partition) const { return {}; }
|
virtual const IOS::ES::TicketReader& GetTicket(const Partition& partition) const
|
||||||
virtual IOS::ES::TMDReader GetTMD(const Partition& partition) const { return {}; }
|
{
|
||||||
|
return INVALID_TICKET;
|
||||||
|
}
|
||||||
|
virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; }
|
||||||
std::string GetGameID() const { return GetGameID(GetGamePartition()); }
|
std::string GetGameID() const { return GetGameID(GetGamePartition()); }
|
||||||
virtual std::string GetGameID(const Partition& partition) const = 0;
|
virtual std::string GetGameID(const Partition& partition) const = 0;
|
||||||
std::string GetMakerID() const { return GetMakerID(GetGamePartition()); }
|
std::string GetMakerID() const { return GetMakerID(GetGamePartition()); }
|
||||||
@ -111,6 +114,9 @@ protected:
|
|||||||
static const size_t NAME_STRING_LENGTH = 42;
|
static const size_t NAME_STRING_LENGTH = 42;
|
||||||
static const size_t NAME_BYTES_LENGTH = NAME_STRING_LENGTH * sizeof(u16);
|
static const size_t NAME_BYTES_LENGTH = NAME_STRING_LENGTH * sizeof(u16);
|
||||||
static const size_t NAMES_TOTAL_BYTES = NAME_BYTES_LENGTH * NUMBER_OF_LANGUAGES;
|
static const size_t NAMES_TOTAL_BYTES = NAME_BYTES_LENGTH * NUMBER_OF_LANGUAGES;
|
||||||
|
|
||||||
|
static const IOS::ES::TicketReader INVALID_TICKET;
|
||||||
|
static const IOS::ES::TMDReader INVALID_TMD;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename);
|
std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename);
|
||||||
|
@ -83,7 +83,7 @@ Country CVolumeWAD::GetCountry(const Partition& partition) const
|
|||||||
return CountrySwitch(country_code);
|
return CountrySwitch(country_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS::ES::TMDReader CVolumeWAD::GetTMD(const Partition& partition) const
|
const IOS::ES::TMDReader& CVolumeWAD::GetTMD(const Partition& partition) const
|
||||||
{
|
{
|
||||||
return m_tmd;
|
return m_tmd;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
bool Read(u64 offset, u64 length, u8* buffer,
|
bool Read(u64 offset, u64 length, u8* buffer,
|
||||||
const Partition& partition = PARTITION_NONE) const override;
|
const Partition& partition = PARTITION_NONE) const override;
|
||||||
bool GetTitleID(u64* buffer, const Partition& partition = PARTITION_NONE) const override;
|
bool GetTitleID(u64* buffer, const Partition& partition = PARTITION_NONE) const override;
|
||||||
IOS::ES::TMDReader GetTMD(const Partition& partition = PARTITION_NONE) const override;
|
const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override;
|
||||||
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
|
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
|
||||||
std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override;
|
std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override;
|
||||||
u16 GetRevision(const Partition& partition = PARTITION_NONE) const override;
|
u16 GetRevision(const Partition& partition = PARTITION_NONE) const override;
|
||||||
|
@ -35,7 +35,7 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader)
|
|||||||
{
|
{
|
||||||
_assert_(m_pReader);
|
_assert_(m_pReader);
|
||||||
|
|
||||||
// Get decryption keys for all partitions
|
// Get tickets, TMDs, and decryption keys for all partitions
|
||||||
for (u32 partition_group = 0; partition_group < 4; ++partition_group)
|
for (u32 partition_group = 0; partition_group < 4; ++partition_group)
|
||||||
{
|
{
|
||||||
u32 number_of_partitions;
|
u32 number_of_partitions;
|
||||||
@ -49,10 +49,12 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader)
|
|||||||
|
|
||||||
for (u32 i = 0; i < number_of_partitions; i++)
|
for (u32 i = 0; i < number_of_partitions; i++)
|
||||||
{
|
{
|
||||||
|
// Read the partition offset
|
||||||
if (!m_pReader->ReadSwapped(partition_table_offset + (i * 8), &read_buffer))
|
if (!m_pReader->ReadSwapped(partition_table_offset + (i * 8), &read_buffer))
|
||||||
continue;
|
continue;
|
||||||
const u64 partition_offset = (u64)read_buffer << 2;
|
const u64 partition_offset = (u64)read_buffer << 2;
|
||||||
|
|
||||||
|
// Set m_game_partition if this is the game partition
|
||||||
if (m_game_partition == PARTITION_NONE)
|
if (m_game_partition == PARTITION_NONE)
|
||||||
{
|
{
|
||||||
u32 partition_type;
|
u32 partition_type;
|
||||||
@ -63,6 +65,36 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader)
|
|||||||
m_game_partition = Partition(partition_offset);
|
m_game_partition = Partition(partition_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read ticket
|
||||||
|
std::vector<u8> ticket_buffer(sizeof(IOS::ES::Ticket));
|
||||||
|
if (!m_pReader->Read(partition_offset, ticket_buffer.size(), ticket_buffer.data()))
|
||||||
|
continue;
|
||||||
|
IOS::ES::TicketReader ticket{std::move(ticket_buffer)};
|
||||||
|
|
||||||
|
// Read TMD
|
||||||
|
u32 tmd_size = 0;
|
||||||
|
u32 tmd_address = 0;
|
||||||
|
if (!m_pReader->ReadSwapped(partition_offset + 0x2a4, &tmd_size))
|
||||||
|
continue;
|
||||||
|
if (!m_pReader->ReadSwapped(partition_offset + 0x2a8, &tmd_address))
|
||||||
|
continue;
|
||||||
|
tmd_address <<= 2;
|
||||||
|
if (tmd_size > 1024 * 1024 * 4)
|
||||||
|
{
|
||||||
|
// The size is checked so that a malicious or corrupt ISO
|
||||||
|
// can't force Dolphin to allocate up to 4 GiB of memory.
|
||||||
|
// 4 MiB should be much bigger than the size of TMDs and much smaller
|
||||||
|
// than the amount of RAM in a computer that can run Dolphin.
|
||||||
|
PanicAlert("TMD > 4 MiB");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::vector<u8> tmd_buffer(tmd_size);
|
||||||
|
if (!m_pReader->Read(partition_offset + tmd_address, tmd_size, tmd_buffer.data()))
|
||||||
|
continue;
|
||||||
|
IOS::ES::TMDReader tmd{std::move(tmd_buffer)};
|
||||||
|
|
||||||
|
// All of the code below is for getting the decryption key
|
||||||
|
|
||||||
u8 sub_key[16];
|
u8 sub_key[16];
|
||||||
if (!m_pReader->Read(partition_offset + 0x1bf, 16, sub_key))
|
if (!m_pReader->Read(partition_offset + 0x1bf, 16, sub_key))
|
||||||
continue;
|
continue;
|
||||||
@ -108,7 +140,13 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader)
|
|||||||
std::unique_ptr<mbedtls_aes_context> partition_AES_context =
|
std::unique_ptr<mbedtls_aes_context> partition_AES_context =
|
||||||
std::make_unique<mbedtls_aes_context>();
|
std::make_unique<mbedtls_aes_context>();
|
||||||
mbedtls_aes_setkey_dec(partition_AES_context.get(), volume_key, 128);
|
mbedtls_aes_setkey_dec(partition_AES_context.get(), volume_key, 128);
|
||||||
m_partitions[Partition(partition_offset)] = std::move(partition_AES_context);
|
|
||||||
|
// We've read everything. Time to store it! (The reason we don't store anything
|
||||||
|
// earlier is because we want to be able to skip adding the partition if an error occurs.)
|
||||||
|
const Partition partition(partition_offset);
|
||||||
|
m_partition_keys[partition] = std::move(partition_AES_context);
|
||||||
|
m_partition_tickets[partition] = std::move(ticket);
|
||||||
|
m_partition_tmds[partition] = std::move(tmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,8 +162,8 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer,
|
|||||||
return m_pReader->Read(_ReadOffset, _Length, _pBuffer);
|
return m_pReader->Read(_ReadOffset, _Length, _pBuffer);
|
||||||
|
|
||||||
// Get the decryption key for the partition
|
// Get the decryption key for the partition
|
||||||
auto it = m_partitions.find(partition);
|
auto it = m_partition_keys.find(partition);
|
||||||
if (it == m_partitions.end())
|
if (it == m_partition_keys.end())
|
||||||
return false;
|
return false;
|
||||||
mbedtls_aes_context* aes_context = it->second.get();
|
mbedtls_aes_context* aes_context = it->second.get();
|
||||||
|
|
||||||
@ -174,7 +212,7 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer,
|
|||||||
std::vector<Partition> CVolumeWiiCrypted::GetPartitions() const
|
std::vector<Partition> CVolumeWiiCrypted::GetPartitions() const
|
||||||
{
|
{
|
||||||
std::vector<Partition> partitions;
|
std::vector<Partition> partitions;
|
||||||
for (const auto& pair : m_partitions)
|
for (const auto& pair : m_partition_keys)
|
||||||
partitions.push_back(pair.first);
|
partitions.push_back(pair.first);
|
||||||
return partitions;
|
return partitions;
|
||||||
}
|
}
|
||||||
@ -189,39 +227,16 @@ bool CVolumeWiiCrypted::GetTitleID(u64* buffer, const Partition& partition) cons
|
|||||||
return m_pReader->ReadSwapped(partition.offset + 0x1DC, buffer);
|
return m_pReader->ReadSwapped(partition.offset + 0x1DC, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS::ES::TicketReader CVolumeWiiCrypted::GetTicket(const Partition& partition) const
|
const IOS::ES::TicketReader& CVolumeWiiCrypted::GetTicket(const Partition& partition) const
|
||||||
{
|
{
|
||||||
std::vector<u8> buffer(0x2a4);
|
auto it = m_partition_tickets.find(partition);
|
||||||
m_pReader->Read(partition.offset, buffer.size(), buffer.data());
|
return it != m_partition_tickets.end() ? it->second : INVALID_TICKET;
|
||||||
return IOS::ES::TicketReader{std::move(buffer)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD(const Partition& partition) const
|
const IOS::ES::TMDReader& CVolumeWiiCrypted::GetTMD(const Partition& partition) const
|
||||||
{
|
{
|
||||||
u32 tmd_size = 0;
|
auto it = m_partition_tmds.find(partition);
|
||||||
u32 tmd_address = 0;
|
return it != m_partition_tmds.end() ? it->second : INVALID_TMD;
|
||||||
|
|
||||||
if (!m_pReader->ReadSwapped(partition.offset + 0x2a4, &tmd_size))
|
|
||||||
return {};
|
|
||||||
if (!m_pReader->ReadSwapped(partition.offset + 0x2a8, &tmd_address))
|
|
||||||
return {};
|
|
||||||
tmd_address <<= 2;
|
|
||||||
|
|
||||||
if (tmd_size > 1024 * 1024 * 4)
|
|
||||||
{
|
|
||||||
// The size is checked so that a malicious or corrupt ISO
|
|
||||||
// can't force Dolphin to allocate up to 4 GiB of memory.
|
|
||||||
// 4 MiB should be much bigger than the size of TMDs and much smaller
|
|
||||||
// than the amount of RAM in a computer that can run Dolphin.
|
|
||||||
PanicAlert("TMD > 4 MiB");
|
|
||||||
tmd_size = 1024 * 1024 * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> buffer(tmd_size);
|
|
||||||
if (!m_pReader->Read(partition.offset + tmd_address, tmd_size, buffer.data()))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return IOS::ES::TMDReader{std::move(buffer)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset, const Partition& partition)
|
u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset, const Partition& partition)
|
||||||
@ -368,8 +383,8 @@ u64 CVolumeWiiCrypted::GetRawSize() const
|
|||||||
bool CVolumeWiiCrypted::CheckIntegrity(const Partition& partition) const
|
bool CVolumeWiiCrypted::CheckIntegrity(const Partition& partition) const
|
||||||
{
|
{
|
||||||
// Get the decryption key for the partition
|
// Get the decryption key for the partition
|
||||||
auto it = m_partitions.find(partition);
|
auto it = m_partition_keys.find(partition);
|
||||||
if (it == m_partitions.end())
|
if (it == m_partition_keys.end())
|
||||||
return false;
|
return false;
|
||||||
mbedtls_aes_context* aes_context = it->second.get();
|
mbedtls_aes_context* aes_context = it->second.get();
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ public:
|
|||||||
std::vector<Partition> GetPartitions() const override;
|
std::vector<Partition> GetPartitions() const override;
|
||||||
Partition GetGamePartition() const override;
|
Partition GetGamePartition() const override;
|
||||||
bool GetTitleID(u64* buffer, const Partition& partition) const override;
|
bool GetTitleID(u64* buffer, const Partition& partition) const override;
|
||||||
IOS::ES::TicketReader GetTicket(const Partition& partition) const override;
|
const IOS::ES::TicketReader& GetTicket(const Partition& partition) const override;
|
||||||
IOS::ES::TMDReader GetTMD(const Partition& partition) const override;
|
const IOS::ES::TMDReader& GetTMD(const Partition& partition) const override;
|
||||||
std::string GetGameID(const Partition& partition) const override;
|
std::string GetGameID(const Partition& partition) const override;
|
||||||
std::string GetMakerID(const Partition& partition) const override;
|
std::string GetMakerID(const Partition& partition) const override;
|
||||||
u16 GetRevision(const Partition& partition) const override;
|
u16 GetRevision(const Partition& partition) const override;
|
||||||
@ -64,7 +64,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<IBlobReader> m_pReader;
|
std::unique_ptr<IBlobReader> m_pReader;
|
||||||
std::map<Partition, std::unique_ptr<mbedtls_aes_context>> m_partitions;
|
std::map<Partition, std::unique_ptr<mbedtls_aes_context>> m_partition_keys;
|
||||||
|
std::map<Partition, IOS::ES::TicketReader> m_partition_tickets;
|
||||||
|
std::map<Partition, IOS::ES::TMDReader> m_partition_tmds;
|
||||||
Partition m_game_partition;
|
Partition m_game_partition;
|
||||||
|
|
||||||
mutable u64 m_last_decrypted_block;
|
mutable u64 m_last_decrypted_block;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user