VolumeWii.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <functional>
  6. #include <map>
  7. #include <memory>
  8. #include <optional>
  9. #include <string>
  10. #include <vector>
  11. #include "Common/CommonTypes.h"
  12. #include "Common/Crypto/SHA1.h"
  13. #include "Common/Lazy.h"
  14. #include "Core/IOS/ES/Formats.h"
  15. #include "DiscIO/Filesystem.h"
  16. #include "DiscIO/Volume.h"
  17. #include "DiscIO/VolumeDisc.h"
  18. #include "Common/Crypto/AES.h"
  19. namespace DiscIO
  20. {
  21. class BlobReader;
  22. enum class BlobType;
  23. enum class Country;
  24. class FileSystem;
  25. enum class Language;
  26. enum class Region;
  27. enum class Platform;
  28. class VolumeWii : public VolumeDisc
  29. {
  30. public:
  31. static constexpr size_t AES_KEY_SIZE = Common::AES::Context::KEY_SIZE;
  32. static constexpr u32 BLOCKS_PER_GROUP = 0x40;
  33. static constexpr u64 BLOCK_HEADER_SIZE = 0x0400;
  34. static constexpr u64 BLOCK_DATA_SIZE = 0x7C00;
  35. static constexpr u64 BLOCK_TOTAL_SIZE = BLOCK_HEADER_SIZE + BLOCK_DATA_SIZE;
  36. static constexpr u64 GROUP_HEADER_SIZE = BLOCK_HEADER_SIZE * BLOCKS_PER_GROUP;
  37. static constexpr u64 GROUP_DATA_SIZE = BLOCK_DATA_SIZE * BLOCKS_PER_GROUP;
  38. static constexpr u64 GROUP_TOTAL_SIZE = GROUP_HEADER_SIZE + GROUP_DATA_SIZE;
  39. struct HashBlock
  40. {
  41. std::array<Common::SHA1::Digest, 31> h0;
  42. std::array<u8, 20> padding_0;
  43. std::array<Common::SHA1::Digest, 8> h1;
  44. std::array<u8, 32> padding_1;
  45. std::array<Common::SHA1::Digest, 8> h2;
  46. std::array<u8, 32> padding_2;
  47. };
  48. static_assert(sizeof(HashBlock) == BLOCK_HEADER_SIZE);
  49. VolumeWii(std::unique_ptr<BlobReader> reader);
  50. ~VolumeWii();
  51. bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const override;
  52. bool HasWiiHashes() const override;
  53. bool HasWiiEncryption() const override;
  54. std::vector<Partition> GetPartitions() const override;
  55. Partition GetGamePartition() const override;
  56. std::optional<u32> GetPartitionType(const Partition& partition) const override;
  57. std::optional<u64> GetTitleID(const Partition& partition) const override;
  58. const IOS::ES::TicketReader& GetTicket(const Partition& partition) const override;
  59. const IOS::ES::TMDReader& GetTMD(const Partition& partition) const override;
  60. const std::vector<u8>& GetCertificateChain(const Partition& partition) const override;
  61. const FileSystem* GetFileSystem(const Partition& partition) const override;
  62. static u64 OffsetInHashedPartitionToRawOffset(u64 offset, const Partition& partition,
  63. u64 partition_data_offset);
  64. u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const override;
  65. std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override;
  66. std::map<Language, std::string> GetLongNames() const override;
  67. std::vector<u32> GetBanner(u32* width, u32* height) const override;
  68. Platform GetVolumeType() const override;
  69. bool IsDatelDisc() const override;
  70. bool CheckH3TableIntegrity(const Partition& partition) const override;
  71. bool CheckBlockIntegrity(u64 block_index, const u8* encrypted_data,
  72. const Partition& partition) const override;
  73. bool CheckBlockIntegrity(u64 block_index, const Partition& partition) const override;
  74. Region GetRegion() const override;
  75. BlobType GetBlobType() const override;
  76. u64 GetDataSize() const override;
  77. DataSizeType GetDataSizeType() const override;
  78. u64 GetRawSize() const override;
  79. const BlobReader& GetBlobReader() const override;
  80. std::array<u8, 20> GetSyncHash() const override;
  81. // The in parameter can either contain all the data to begin with,
  82. // or read_function can write data into the in parameter when called.
  83. // The latter lets reading run in parallel with hashing.
  84. // This function returns false iff read_function returns false.
  85. static bool HashGroup(const std::array<u8, BLOCK_DATA_SIZE> in[BLOCKS_PER_GROUP],
  86. HashBlock out[BLOCKS_PER_GROUP],
  87. const std::function<bool(size_t block)>& read_function = {});
  88. static bool EncryptGroup(u64 offset, u64 partition_data_offset, u64 partition_data_decrypted_size,
  89. const std::array<u8, AES_KEY_SIZE>& key, BlobReader* blob,
  90. std::array<u8, GROUP_TOTAL_SIZE>* out,
  91. const std::function<void(HashBlock hash_blocks[BLOCKS_PER_GROUP])>&
  92. hash_exception_callback = {});
  93. static void DecryptBlockHashes(const u8* in, HashBlock* out, Common::AES::Context* aes_context);
  94. static void DecryptBlockData(const u8* in, u8* out, Common::AES::Context* aes_context);
  95. protected:
  96. u32 GetOffsetShift() const override { return 2; }
  97. private:
  98. struct PartitionDetails
  99. {
  100. Common::Lazy<std::unique_ptr<Common::AES::Context>> key;
  101. Common::Lazy<IOS::ES::TicketReader> ticket;
  102. Common::Lazy<IOS::ES::TMDReader> tmd;
  103. Common::Lazy<std::vector<u8>> cert_chain;
  104. Common::Lazy<std::vector<u8>> h3_table;
  105. Common::Lazy<std::unique_ptr<FileSystem>> file_system;
  106. Common::Lazy<u64> data_offset;
  107. u32 type = 0;
  108. };
  109. std::unique_ptr<BlobReader> m_reader;
  110. std::map<Partition, PartitionDetails> m_partitions;
  111. Partition m_game_partition;
  112. bool m_has_hashes;
  113. bool m_has_encryption;
  114. mutable u64 m_last_decrypted_block;
  115. mutable u8 m_last_decrypted_block_data[BLOCK_DATA_SIZE]{};
  116. };
  117. } // namespace DiscIO