| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2008 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <cstddef>
 | 
					
						
							|  |  |  | #include <cstring>
 | 
					
						
							| 
									
										
										
										
											2015-04-09 17:44:53 +02:00
										 |  |  | #include <map>
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include <mbedtls/aes.h>
 | 
					
						
							|  |  |  | #include <mbedtls/sha1.h>
 | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 23:17:41 -05:00
										 |  |  | #include "Common/CommonFuncs.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-07 20:06:58 -05:00
										 |  |  | #include "Common/CommonTypes.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-18 23:17:41 -05:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "Common/MsgHandler.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include "DiscIO/Blob.h"
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | #include "DiscIO/Enums.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-25 11:01:18 +01:00
										 |  |  | #include "DiscIO/FileMonitor.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-10 23:18:41 +02:00
										 |  |  | #include "DiscIO/Filesystem.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include "DiscIO/Volume.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-29 03:38:39 -07:00
										 |  |  | #include "DiscIO/VolumeCreator.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "DiscIO/VolumeGC.h"
 | 
					
						
							|  |  |  | #include "DiscIO/VolumeWiiCrypted.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | namespace DiscIO | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader, u64 _VolumeOffset, | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |                                      const unsigned char* _pVolumeKey) | 
					
						
							|  |  |  |     : m_pReader(std::move(reader)), m_AES_ctx(std::make_unique<mbedtls_aes_context>()), | 
					
						
							|  |  |  |       m_VolumeOffset(_VolumeOffset), m_dataOffset(0x20000), m_LastDecryptedBlockOffset(-1) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   mbedtls_aes_setkey_dec(m_AES_ctx.get(), _pVolumeKey, 128); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-29 03:38:39 -07:00
										 |  |  | bool CVolumeWiiCrypted::ChangePartition(u64 offset) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   m_VolumeOffset = offset; | 
					
						
							|  |  |  |   m_LastDecryptedBlockOffset = -1; | 
					
						
							| 
									
										
										
										
											2014-05-29 03:38:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u8 volume_key[16]; | 
					
						
							|  |  |  |   DiscIO::VolumeKeyForPartition(*m_pReader, offset, volume_key); | 
					
						
							|  |  |  |   mbedtls_aes_setkey_dec(m_AES_ctx.get(), volume_key, 128); | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2014-05-29 03:38:39 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | CVolumeWiiCrypted::~CVolumeWiiCrypted() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:35:48 +01:00
										 |  |  | bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool decrypt) const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!decrypt) | 
					
						
							|  |  |  |     return m_pReader->Read(_ReadOffset, _Length, _pBuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   FileMon::FindFilename(_ReadOffset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 16:56:40 +01:00
										 |  |  |   std::vector<u8> read_buffer(BLOCK_TOTAL_SIZE); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   while (_Length > 0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Calculate block offset
 | 
					
						
							| 
									
										
										
										
											2017-02-10 16:56:40 +01:00
										 |  |  |     u64 Block = _ReadOffset / BLOCK_DATA_SIZE; | 
					
						
							|  |  |  |     u64 Offset = _ReadOffset % BLOCK_DATA_SIZE; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_LastDecryptedBlockOffset != Block) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Read the current block
 | 
					
						
							| 
									
										
										
										
											2017-02-10 16:56:40 +01:00
										 |  |  |       if (!m_pReader->Read(m_VolumeOffset + m_dataOffset + Block * BLOCK_TOTAL_SIZE, | 
					
						
							|  |  |  |                            BLOCK_TOTAL_SIZE, read_buffer.data())) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Decrypt the block's data.
 | 
					
						
							|  |  |  |       // 0x3D0 - 0x3DF in m_pBuffer will be overwritten,
 | 
					
						
							|  |  |  |       // but that won't affect anything, because we won't
 | 
					
						
							|  |  |  |       // use the content of m_pBuffer anymore after this
 | 
					
						
							| 
									
										
										
										
											2017-02-10 16:56:40 +01:00
										 |  |  |       mbedtls_aes_crypt_cbc(m_AES_ctx.get(), MBEDTLS_AES_DECRYPT, BLOCK_DATA_SIZE, | 
					
						
							|  |  |  |                             &read_buffer[0x3D0], &read_buffer[BLOCK_HEADER_SIZE], | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |                             m_LastDecryptedBlock); | 
					
						
							|  |  |  |       m_LastDecryptedBlockOffset = Block; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // The only thing we currently use from the 0x000 - 0x3FF part
 | 
					
						
							|  |  |  |       // of the block is the IV (at 0x3D0), but it also contains SHA-1
 | 
					
						
							|  |  |  |       // hashes that IOS uses to check that discs aren't tampered with.
 | 
					
						
							|  |  |  |       // http://wiibrew.org/wiki/Wii_Disc#Encrypted
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Copy the decrypted data
 | 
					
						
							| 
									
										
										
										
											2017-02-10 16:56:40 +01:00
										 |  |  |     u64 MaxSizeToCopy = BLOCK_DATA_SIZE - Offset; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length; | 
					
						
							|  |  |  |     memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Update offsets
 | 
					
						
							|  |  |  |     _Length -= CopySize; | 
					
						
							|  |  |  |     _pBuffer += CopySize; | 
					
						
							|  |  |  |     _ReadOffset += CopySize; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 13:25:54 -04:00
										 |  |  | bool CVolumeWiiCrypted::GetTitleID(u64* buffer) const | 
					
						
							| 
									
										
										
										
											2010-01-14 07:19:10 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Tik is at m_VolumeOffset size 0x2A4
 | 
					
						
							|  |  |  |   // TitleID offset in tik is 0x1DC
 | 
					
						
							|  |  |  |   if (!Read(m_VolumeOffset + 0x1DC, sizeof(u64), reinterpret_cast<u8*>(buffer), false)) | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2015-09-22 13:25:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   *buffer = Common::swap64(*buffer); | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2010-01-14 07:19:10 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-03 10:54:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-19 17:52:10 -05:00
										 |  |  | std::vector<u8> CVolumeWiiCrypted::GetTMD() const | 
					
						
							| 
									
										
										
										
											2010-09-08 00:20:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 tmd_size; | 
					
						
							|  |  |  |   u32 tmd_address; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Read(m_VolumeOffset + 0x2a4, sizeof(u32), (u8*)&tmd_size, false); | 
					
						
							|  |  |  |   Read(m_VolumeOffset + 0x2a8, sizeof(u32), (u8*)&tmd_address, false); | 
					
						
							|  |  |  |   tmd_size = Common::swap32(tmd_size); | 
					
						
							|  |  |  |   tmd_address = Common::swap32(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); | 
					
						
							|  |  |  |   Read(m_VolumeOffset + tmd_address, tmd_size, buffer.data(), false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return buffer; | 
					
						
							| 
									
										
										
										
											2010-09-08 00:20:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 18:57:58 +01:00
										 |  |  | u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_VolumeOffset + m_dataOffset + (offset / BLOCK_DATA_SIZE * BLOCK_TOTAL_SIZE) + | 
					
						
							|  |  |  |          (offset % BLOCK_DATA_SIZE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 14:42:43 +02:00
										 |  |  | std::string CVolumeWiiCrypted::GetGameID() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char ID[6]; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(0, 6, (u8*)ID, false)) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return DecodeString(ID); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  | Region CVolumeWiiCrypted::GetRegion() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   u32 region_code; | 
					
						
							|  |  |  |   if (!ReadSwapped(0x4E000, ®ion_code, false)) | 
					
						
							|  |  |  |     return Region::UNKNOWN_REGION; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return static_cast<Region>(region_code); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  | Country CVolumeWiiCrypted::GetCountry() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u8 country_byte; | 
					
						
							|  |  |  |   if (!m_pReader->Read(3, 1, &country_byte)) | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |     return Country::COUNTRY_UNKNOWN; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   const Region region = GetRegion(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   if (RegionSwitchWii(country_byte) == region) | 
					
						
							|  |  |  |     return CountrySwitch(country_byte); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   switch (region) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   case Region::NTSC_J: | 
					
						
							|  |  |  |     return Country::COUNTRY_JAPAN; | 
					
						
							|  |  |  |   case Region::NTSC_U: | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |     return Country::COUNTRY_USA; | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   case Region::PAL: | 
					
						
							|  |  |  |     return Country::COUNTRY_EUROPE; | 
					
						
							|  |  |  |   case Region::NTSC_K: | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |     return Country::COUNTRY_KOREA; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   default: | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |     return Country::COUNTRY_UNKNOWN; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-21 19:19:15 +00:00
										 |  |  | std::string CVolumeWiiCrypted::GetMakerID() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char makerID[2]; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(0x4, 0x2, (u8*)&makerID, false)) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return DecodeString(makerID); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 21:14:02 +02:00
										 |  |  | u16 CVolumeWiiCrypted::GetRevision() const | 
					
						
							| 
									
										
										
										
											2014-11-14 20:59:39 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!m_pReader) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2014-11-14 20:59:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u8 revision; | 
					
						
							|  |  |  |   if (!m_pReader->Read(7, 1, &revision)) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2014-11-14 20:59:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return revision; | 
					
						
							| 
									
										
										
										
											2014-11-14 20:59:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-11 11:19:30 +02:00
										 |  |  | std::string CVolumeWiiCrypted::GetInternalName() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char name_buffer[0x60]; | 
					
						
							|  |  |  |   if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name_buffer, false)) | 
					
						
							|  |  |  |     return DecodeString(name_buffer); | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return ""; | 
					
						
							| 
									
										
										
										
											2015-04-10 22:10:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | std::map<Language, std::string> CVolumeWiiCrypted::GetLongNames() const | 
					
						
							| 
									
										
										
										
											2015-04-10 22:10:49 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); | 
					
						
							|  |  |  |   std::vector<u8> opening_bnr(NAMES_TOTAL_BYTES); | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |   size_t size = file_system->ReadFile("opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C); | 
					
						
							|  |  |  |   opening_bnr.resize(size); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return ReadWiiNames(opening_bnr); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | std::vector<u32> CVolumeWiiCrypted::GetBanner(int* width, int* height) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   *width = 0; | 
					
						
							|  |  |  |   *height = 0; | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u64 title_id; | 
					
						
							|  |  |  |   if (!GetTitleID(&title_id)) | 
					
						
							|  |  |  |     return std::vector<u32>(); | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return GetWiiBanner(width, height, title_id); | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-10 16:35:23 +02:00
										 |  |  | u64 CVolumeWiiCrypted::GetFSTSize() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 size; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(0x428, 0x4, (u8*)&size, true)) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return (u64)Common::swap32(size) << 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-21 19:19:15 +00:00
										 |  |  | std::string CVolumeWiiCrypted::GetApploaderDate() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char date[16]; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(0x2440, 0x10, (u8*)&date, true)) | 
					
						
							|  |  |  |     return std::string(); | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return DecodeString(date); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | Platform CVolumeWiiCrypted::GetVolumeType() const | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |   return Platform::WII_DISC; | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 21:14:02 +02:00
										 |  |  | u8 CVolumeWiiCrypted::GetDiscNumber() const | 
					
						
							| 
									
										
										
										
											2015-02-26 17:10:18 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u8 disc_number; | 
					
						
							|  |  |  |   m_pReader->Read(6, 1, &disc_number); | 
					
						
							|  |  |  |   return disc_number; | 
					
						
							| 
									
										
										
										
											2015-02-26 17:10:18 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-27 14:01:12 +02:00
										 |  |  | BlobType CVolumeWiiCrypted::GetBlobType() const | 
					
						
							| 
									
										
										
										
											2015-09-26 15:24:29 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return m_pReader ? m_pReader->GetBlobType() : BlobType::PLAIN; | 
					
						
							| 
									
										
										
										
											2015-09-26 15:24:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-21 19:19:15 +00:00
										 |  |  | u64 CVolumeWiiCrypted::GetSize() const | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader) | 
					
						
							|  |  |  |     return m_pReader->GetDataSize(); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-22 13:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-09 12:58:56 -05:00
										 |  |  | u64 CVolumeWiiCrypted::GetRawSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader) | 
					
						
							|  |  |  |     return m_pReader->GetRawSize(); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2013-04-09 12:58:56 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-04 12:49:10 +02:00
										 |  |  | bool CVolumeWiiCrypted::CheckIntegrity() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Get partition data size
 | 
					
						
							|  |  |  |   u32 partSizeDiv4; | 
					
						
							|  |  |  |   Read(m_VolumeOffset + 0x2BC, 4, (u8*)&partSizeDiv4, false); | 
					
						
							|  |  |  |   u64 partDataSize = (u64)Common::swap32(partSizeDiv4) * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   u32 nClusters = (u32)(partDataSize / 0x8000); | 
					
						
							|  |  |  |   for (u32 clusterID = 0; clusterID < nClusters; ++clusterID) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     u64 clusterOff = m_VolumeOffset + m_dataOffset + (u64)clusterID * 0x8000; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Read and decrypt the cluster metadata
 | 
					
						
							|  |  |  |     u8 clusterMDCrypted[0x400]; | 
					
						
							|  |  |  |     u8 clusterMD[0x400]; | 
					
						
							|  |  |  |     u8 IV[16] = {0}; | 
					
						
							|  |  |  |     if (!m_pReader->Read(clusterOff, 0x400, clusterMDCrypted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-24 19:06:47 -04:00
										 |  |  |       WARN_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read metadata", clusterID); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mbedtls_aes_crypt_cbc(m_AES_ctx.get(), MBEDTLS_AES_DECRYPT, 0x400, IV, clusterMDCrypted, | 
					
						
							|  |  |  |                           clusterMD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Some clusters have invalid data and metadata because they aren't
 | 
					
						
							|  |  |  |     // meant to be read by the game (for example, holes between files). To
 | 
					
						
							|  |  |  |     // try to avoid reporting errors because of these clusters, we check
 | 
					
						
							|  |  |  |     // the 0x00 paddings in the metadata.
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // This may cause some false negatives though: some bad clusters may be
 | 
					
						
							|  |  |  |     // skipped because they are *too* bad and are not even recognized as
 | 
					
						
							|  |  |  |     // valid clusters. To be improved.
 | 
					
						
							|  |  |  |     bool meaningless = false; | 
					
						
							|  |  |  |     for (u32 idx = 0x26C; idx < 0x280; ++idx) | 
					
						
							|  |  |  |       if (clusterMD[idx] != 0) | 
					
						
							|  |  |  |         meaningless = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (meaningless) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u8 clusterData[0x7C00]; | 
					
						
							|  |  |  |     if (!Read((u64)clusterID * 0x7C00, 0x7C00, clusterData, true)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-24 19:06:47 -04:00
										 |  |  |       WARN_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read data", clusterID); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (u32 hashID = 0; hashID < 31; ++hashID) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       u8 hash[20]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mbedtls_sha1(clusterData + hashID * 0x400, 0x400, hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Note that we do not use strncmp here
 | 
					
						
							|  |  |  |       if (memcmp(hash, clusterMD + hashID * 20, 20)) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2016-09-24 19:06:47 -04:00
										 |  |  |         WARN_LOG(DISCIO, "Integrity Check: fail at cluster %d: hash %d is invalid", clusterID, | 
					
						
							|  |  |  |                  hashID); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2012-05-04 12:49:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | }  // namespace
 |