diff --git a/Source/Core/Core/IOS/Network/KD/NWC24DL.cpp b/Source/Core/Core/IOS/Network/KD/NWC24DL.cpp index 2dac60819d..e61f3abbf1 100644 --- a/Source/Core/Core/IOS/Network/KD/NWC24DL.cpp +++ b/Source/Core/Core/IOS/Network/KD/NWC24DL.cpp @@ -120,6 +120,11 @@ bool NWC24Dl::IsEncrypted(u16 entry_index) const return !!Common::ExtractBit(Common::swap32(m_data.entries[entry_index].flags), 3); } +bool NWC24Dl::IsRSASigned(u16 entry_index) const +{ + return !Common::ExtractBit(Common::swap32(m_data.entries[entry_index].flags), 2); +} + u32 NWC24Dl::Magic() const { return Common::swap32(m_data.header.magic); diff --git a/Source/Core/Core/IOS/Network/KD/NWC24DL.h b/Source/Core/Core/IOS/Network/KD/NWC24DL.h index 1704d15223..e5427ea2ea 100644 --- a/Source/Core/Core/IOS/Network/KD/NWC24DL.h +++ b/Source/Core/Core/IOS/Network/KD/NWC24DL.h @@ -29,6 +29,7 @@ public: bool DoesEntryExist(u16 entry_index); bool IsEncrypted(u16 entry_index) const; + bool IsRSASigned(u16 entry_index) const; std::string GetVFFContentName(u16 entry_index, std::optional subtask_id) const; std::string GetDownloadURL(u16 entry_index, std::optional subtask_id) const; std::string GetVFFPath(u16 entry_index) const; diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp index b59c365155..856ce9860f 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -255,32 +255,48 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index, return NWC24::WC24_ERR_SERVER; } - // Check if the filesize is smaller than the header size. - if (response->size() < sizeof(NWC24::WC24File)) + if (!m_dl_list.IsRSASigned(entry_index)) { - ERROR_LOG_FMT(IOS_WC24, "File at {} is too small to be a valid file.", url); - LogError(ErrorType::KD_Download, NWC24::WC24_ERR_BROKEN); - return NWC24::WC24_ERR_BROKEN; - } + // Data that is not signed with an RSA key will not have the WC24 header or 320 bytes before the + // actual data. We just have to make sure that the response is not empty. + if (response->empty()) + { + ERROR_LOG_FMT(IOS_WC24, "File at {} is empty.", url); + LogError(ErrorType::KD_Download, NWC24::WC24_ERR_BROKEN); + return NWC24::WC24_ERR_BROKEN; + } - // Now we read the file - NWC24::WC24File wc24File; - std::memcpy(&wc24File, response->data(), sizeof(NWC24::WC24File)); - - std::vector temp_buffer(response->begin() + 320, response->end()); - - if (m_dl_list.IsEncrypted(entry_index)) - { - NWC24::WC24PubkMod pubkMod = m_dl_list.GetWC24PubkMod(entry_index); - - file_data = std::vector(response->size() - 320); - - Common::AES::CryptOFB(pubkMod.aes_key, wc24File.iv, wc24File.iv, temp_buffer.data(), - file_data.data(), temp_buffer.size()); + file_data = *response; } else { - file_data = std::move(temp_buffer); + // Check if the filesize is smaller than the header size. + if (response->size() < sizeof(NWC24::WC24File)) + { + ERROR_LOG_FMT(IOS_WC24, "File at {} is too small to be a valid file.", url); + LogError(ErrorType::KD_Download, NWC24::WC24_ERR_BROKEN); + return NWC24::WC24_ERR_BROKEN; + } + + // Now we read the file + NWC24::WC24File wc24_file; + std::memcpy(&wc24_file, response->data(), sizeof(NWC24::WC24File)); + + std::vector temp_buffer(response->begin() + 320, response->end()); + + if (m_dl_list.IsEncrypted(entry_index)) + { + NWC24::WC24PubkMod pubk_mod = m_dl_list.GetWC24PubkMod(entry_index); + + file_data = std::vector(response->size() - 320); + + Common::AES::CryptOFB(pubk_mod.aes_key, wc24_file.iv, wc24_file.iv, temp_buffer.data(), + file_data.data(), temp_buffer.size()); + } + else + { + file_data = std::move(temp_buffer); + } } NWC24::ErrorCode reply = IOS::HLE::NWC24::OpenVFF(m_dl_list.GetVFFPath(entry_index), content_name,