diff --git a/Source/Core/DiscIO/Volume.cpp b/Source/Core/DiscIO/Volume.cpp index e95a2b746f..8aba2c981b 100644 --- a/Source/Core/DiscIO/Volume.cpp +++ b/Source/Core/DiscIO/Volume.cpp @@ -25,6 +25,7 @@ namespace DiscIO { const IOS::ES::TicketReader Volume::INVALID_TICKET{}; const IOS::ES::TMDReader Volume::INVALID_TMD{}; +const std::vector Volume::INVALID_CERT_CHAIN{}; std::map Volume::ReadWiiNames(const std::vector& data) { diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index c7c8e5849a..e5e77d4479 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -69,6 +69,10 @@ public: return INVALID_TICKET; } virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; } + virtual const std::vector& GetCertificateChain(const Partition& partition) const + { + return INVALID_CERT_CHAIN; + } // Returns a non-owning pointer. Returns nullptr if the file system couldn't be read. virtual const FileSystem* GetFileSystem(const Partition& partition) const = 0; virtual u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const @@ -129,8 +133,9 @@ protected: static const IOS::ES::TicketReader INVALID_TICKET; static const IOS::ES::TMDReader INVALID_TMD; + static const std::vector INVALID_CERT_CHAIN; }; std::unique_ptr CreateVolumeFromFilename(const std::string& filename); -} // namespace +} // namespace DiscIO diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp index 48a315331b..94191c05c7 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -32,14 +32,14 @@ VolumeWAD::VolumeWAD(std::unique_ptr reader) : m_reader(std::move(re // Source: http://wiibrew.org/wiki/WAD_files m_hdr_size = m_reader->ReadSwapped(0x00).value_or(0); - m_cert_size = m_reader->ReadSwapped(0x08).value_or(0); + m_cert_chain_size = m_reader->ReadSwapped(0x08).value_or(0); m_ticket_size = m_reader->ReadSwapped(0x10).value_or(0); m_tmd_size = m_reader->ReadSwapped(0x14).value_or(0); m_data_size = m_reader->ReadSwapped(0x18).value_or(0); - m_ticket_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40); - m_tmd_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40) + - Common::AlignUp(m_ticket_size, 0x40); + m_cert_chain_offset = Common::AlignUp(m_hdr_size, 0x40); + m_ticket_offset = m_cert_chain_offset + Common::AlignUp(m_cert_chain_size, 0x40); + m_tmd_offset = m_ticket_offset + Common::AlignUp(m_ticket_size, 0x40); m_opening_bnr_offset = m_tmd_offset + Common::AlignUp(m_tmd_size, 0x40) + Common::AlignUp(m_data_size, 0x40); @@ -56,6 +56,9 @@ VolumeWAD::VolumeWAD(std::unique_ptr reader) : m_reader(std::move(re std::vector tmd_buffer(m_tmd_size); Read(m_tmd_offset, m_tmd_size, tmd_buffer.data()); m_tmd.SetBytes(std::move(tmd_buffer)); + + m_cert_chain.resize(m_cert_chain_size); + Read(m_cert_chain_offset, m_cert_chain_size, m_cert_chain.data()); } VolumeWAD::~VolumeWAD() @@ -109,6 +112,11 @@ const IOS::ES::TMDReader& VolumeWAD::GetTMD(const Partition& partition) const return m_tmd; } +const std::vector& VolumeWAD::GetCertificateChain(const Partition& partition) const +{ + return m_cert_chain; +} + std::string VolumeWAD::GetGameID(const Partition& partition) const { return m_tmd.GetGameID(); diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index 02276f7797..42da715b9e 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -36,6 +36,8 @@ public: const IOS::ES::TicketReader& GetTicket(const Partition& partition = PARTITION_NONE) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override; + const std::vector& + GetCertificateChain(const Partition& partition = PARTITION_NONE) const override; std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override; std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; @@ -63,11 +65,13 @@ private: std::unique_ptr m_reader; IOS::ES::TicketReader m_ticket; IOS::ES::TMDReader m_tmd; + std::vector m_cert_chain; + u32 m_cert_chain_offset = 0; u32 m_ticket_offset = 0; u32 m_tmd_offset = 0; u32 m_opening_bnr_offset = 0; u32 m_hdr_size = 0; - u32 m_cert_size = 0; + u32 m_cert_chain_size = 0; u32 m_ticket_size = 0; u32 m_tmd_size = 0; u32 m_data_size = 0; diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp index f7261b0a61..f5b0a253cc 100644 --- a/Source/Core/DiscIO/VolumeWii.cpp +++ b/Source/Core/DiscIO/VolumeWii.cpp @@ -97,6 +97,18 @@ VolumeWii::VolumeWii(std::unique_ptr reader) return IOS::ES::TMDReader{std::move(tmd_buffer)}; }; + auto get_cert_chain = [this, partition]() -> std::vector { + const std::optional size = m_reader->ReadSwapped(partition.offset + 0x2ac); + const std::optional address = + ReadSwappedAndShifted(partition.offset + 0x2b0, PARTITION_NONE); + if (!size || !address) + return {}; + std::vector cert_chain(*size); + if (!m_reader->Read(partition.offset + *address, *size, cert_chain.data())) + return {}; + return cert_chain; + }; + auto get_key = [this, partition]() -> std::unique_ptr { const IOS::ES::TicketReader& ticket = *m_partitions[partition].ticket; if (!ticket.IsValid()) @@ -120,6 +132,7 @@ VolumeWii::VolumeWii(std::unique_ptr reader) partition, PartitionDetails{Common::Lazy>(get_key), Common::Lazy(get_ticket), Common::Lazy(get_tmd), + Common::Lazy>(get_cert_chain), Common::Lazy>(get_file_system), Common::Lazy(get_data_offset), *partition_type}); } @@ -239,6 +252,12 @@ const IOS::ES::TMDReader& VolumeWii::GetTMD(const Partition& partition) const return it != m_partitions.end() ? *it->second.tmd : INVALID_TMD; } +const std::vector& VolumeWii::GetCertificateChain(const Partition& partition) const +{ + auto it = m_partitions.find(partition); + return it != m_partitions.end() ? *it->second.cert_chain : INVALID_CERT_CHAIN; +} + const FileSystem* VolumeWii::GetFileSystem(const Partition& partition) const { auto it = m_partitions.find(partition); @@ -468,4 +487,4 @@ bool VolumeWii::CheckIntegrity(const Partition& partition) const return true; } -} // namespace +} // namespace DiscIO diff --git a/Source/Core/DiscIO/VolumeWii.h b/Source/Core/DiscIO/VolumeWii.h index e2b82c79f2..e6b7e4117d 100644 --- a/Source/Core/DiscIO/VolumeWii.h +++ b/Source/Core/DiscIO/VolumeWii.h @@ -40,6 +40,7 @@ public: std::optional GetTitleID(const Partition& partition) const override; const IOS::ES::TicketReader& GetTicket(const Partition& partition) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition) const override; + const std::vector& GetCertificateChain(const Partition& partition) const override; const FileSystem* GetFileSystem(const Partition& partition) const override; static u64 EncryptedPartitionOffsetToRawOffset(u64 offset, const Partition& partition, u64 partition_data_offset); @@ -78,6 +79,7 @@ private: Common::Lazy> key; Common::Lazy ticket; Common::Lazy tmd; + Common::Lazy> cert_chain; Common::Lazy> file_system; Common::Lazy data_offset; u32 type;