diff options
| author | 2018-08-18 21:14:57 -0400 | |
|---|---|---|
| committer | 2018-08-23 11:53:30 -0400 | |
| commit | 42dc856ce136c75f587649863ec5bd936ba8b07a (patch) | |
| tree | 5b270705a38cc4187a5634f753c9caa2f398dfb8 /src | |
| parent | key_manager: Add support for autogenerated keys (diff) | |
| download | yuzu-42dc856ce136c75f587649863ec5bd936ba8b07a.tar.gz yuzu-42dc856ce136c75f587649863ec5bd936ba8b07a.tar.xz yuzu-42dc856ce136c75f587649863ec5bd936ba8b07a.zip | |
crypto: Eliminate magic constants
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/crypto/key_manager.cpp | 2 | ||||
| -rw-r--r-- | src/core/crypto/xts_encryption_layer.cpp | 33 | ||||
| -rw-r--r-- | src/core/file_sys/xts_archive.cpp | 25 | ||||
| -rw-r--r-- | src/core/file_sys/xts_archive.h | 10 |
4 files changed, 38 insertions, 32 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 994ac4eec..acf635a65 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -102,7 +102,7 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, const KeyManag | |||
| 102 | 102 | ||
| 103 | AESCipher<Key128> cipher(sd_kek, Mode::ECB); | 103 | AESCipher<Key128> cipher(sd_kek, Mode::ECB); |
| 104 | for (size_t i = 0; i < 2; ++i) { | 104 | for (size_t i = 0; i < 2; ++i) { |
| 105 | for (size_t j = 0; j < 0x20; ++j) | 105 | for (size_t j = 0; j < sd_key_sources[i].size(); ++j) |
| 106 | sd_key_sources[i][j] ^= sd_seed[j & 0xF]; | 106 | sd_key_sources[i][j] ^= sd_seed[j & 0xF]; |
| 107 | cipher.Transcode(sd_key_sources[i].data(), sd_key_sources[i].size(), sd_keys[i].data(), | 107 | cipher.Transcode(sd_key_sources[i].data(), sd_key_sources[i].size(), sd_keys[i].data(), |
| 108 | Op::Decrypt); | 108 | Op::Decrypt); |
diff --git a/src/core/crypto/xts_encryption_layer.cpp b/src/core/crypto/xts_encryption_layer.cpp index 431099580..c6e5df1ce 100644 --- a/src/core/crypto/xts_encryption_layer.cpp +++ b/src/core/crypto/xts_encryption_layer.cpp | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace Core::Crypto { | 9 | namespace Core::Crypto { |
| 10 | 10 | ||
| 11 | constexpr u64 XTS_SECTOR_SIZE = 0x4000; | ||
| 12 | |||
| 11 | XTSEncryptionLayer::XTSEncryptionLayer(FileSys::VirtualFile base_, Key256 key_) | 13 | XTSEncryptionLayer::XTSEncryptionLayer(FileSys::VirtualFile base_, Key256 key_) |
| 12 | : EncryptionLayer(std::move(base_)), cipher(key_, Mode::XTS) {} | 14 | : EncryptionLayer(std::move(base_)), cipher(key_, Mode::XTS) {} |
| 13 | 15 | ||
| @@ -17,34 +19,35 @@ size_t XTSEncryptionLayer::Read(u8* data, size_t length, size_t offset) const { | |||
| 17 | 19 | ||
| 18 | const auto sector_offset = offset & 0x3FFF; | 20 | const auto sector_offset = offset & 0x3FFF; |
| 19 | if (sector_offset == 0) { | 21 | if (sector_offset == 0) { |
| 20 | if (length % 0x4000 == 0) { | 22 | if (length % XTS_SECTOR_SIZE == 0) { |
| 21 | std::vector<u8> raw = base->ReadBytes(length, offset); | 23 | std::vector<u8> raw = base->ReadBytes(length, offset); |
| 22 | cipher.XTSTranscode(raw.data(), raw.size(), data, offset / 0x4000, 0x4000, Op::Decrypt); | 24 | cipher.XTSTranscode(raw.data(), raw.size(), data, offset / XTS_SECTOR_SIZE, |
| 25 | XTS_SECTOR_SIZE, Op::Decrypt); | ||
| 23 | return raw.size(); | 26 | return raw.size(); |
| 24 | } | 27 | } |
| 25 | if (length > 0x4000) { | 28 | if (length > XTS_SECTOR_SIZE) { |
| 26 | const auto rem = length % 0x4000; | 29 | const auto rem = length % XTS_SECTOR_SIZE; |
| 27 | const auto read = length - rem; | 30 | const auto read = length - rem; |
| 28 | return Read(data, read, offset) + Read(data + read, rem, offset + read); | 31 | return Read(data, read, offset) + Read(data + read, rem, offset + read); |
| 29 | } | 32 | } |
| 30 | std::vector<u8> buffer = base->ReadBytes(0x4000, offset); | 33 | std::vector<u8> buffer = base->ReadBytes(XTS_SECTOR_SIZE, offset); |
| 31 | if (buffer.size() < 0x4000) | 34 | if (buffer.size() < XTS_SECTOR_SIZE) |
| 32 | buffer.resize(0x4000); | 35 | buffer.resize(XTS_SECTOR_SIZE); |
| 33 | cipher.XTSTranscode(buffer.data(), buffer.size(), buffer.data(), offset / 0x4000, 0x4000, | 36 | cipher.XTSTranscode(buffer.data(), buffer.size(), buffer.data(), offset / XTS_SECTOR_SIZE, |
| 34 | Op::Decrypt); | 37 | XTS_SECTOR_SIZE, Op::Decrypt); |
| 35 | std::memcpy(data, buffer.data(), std::min(buffer.size(), length)); | 38 | std::memcpy(data, buffer.data(), std::min(buffer.size(), length)); |
| 36 | return std::min(buffer.size(), length); | 39 | return std::min(buffer.size(), length); |
| 37 | } | 40 | } |
| 38 | 41 | ||
| 39 | // offset does not fall on block boundary (0x4000) | 42 | // offset does not fall on block boundary (0x4000) |
| 40 | std::vector<u8> block = base->ReadBytes(0x4000, offset - sector_offset); | 43 | std::vector<u8> block = base->ReadBytes(0x4000, offset - sector_offset); |
| 41 | if (block.size() < 0x4000) | 44 | if (block.size() < XTS_SECTOR_SIZE) |
| 42 | block.resize(0x4000); | 45 | block.resize(XTS_SECTOR_SIZE); |
| 43 | cipher.XTSTranscode(block.data(), block.size(), block.data(), (offset - sector_offset) / 0x4000, | 46 | cipher.XTSTranscode(block.data(), block.size(), block.data(), |
| 44 | 0x4000, Op::Decrypt); | 47 | (offset - sector_offset) / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt); |
| 45 | const size_t read = 0x4000 - sector_offset; | 48 | const size_t read = XTS_SECTOR_SIZE - sector_offset; |
| 46 | 49 | ||
| 47 | if (length + sector_offset < 0x4000) { | 50 | if (length + sector_offset < XTS_SECTOR_SIZE) { |
| 48 | std::memcpy(data, block.data() + sector_offset, std::min<u64>(length, read)); | 51 | std::memcpy(data, block.data() + sector_offset, std::min<u64>(length, read)); |
| 49 | return std::min<u64>(length, read); | 52 | return std::min<u64>(length, read); |
| 50 | } | 53 | } |
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 54be31916..605c1a283 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | namespace FileSys { | 20 | namespace FileSys { |
| 21 | 21 | ||
| 22 | constexpr u64 NAX_HEADER_PADDING_SIZE = 0x4000; | ||
| 23 | |||
| 22 | template <typename SourceData, typename SourceKey, typename Destination> | 24 | template <typename SourceData, typename SourceKey, typename Destination> |
| 23 | static bool CalculateHMAC256(Destination* out, const SourceKey* key, size_t key_length, | 25 | static bool CalculateHMAC256(Destination* out, const SourceKey* key, size_t key_length, |
| 24 | const SourceData* data, size_t data_length) { | 26 | const SourceData* data, size_t data_length) { |
| @@ -67,14 +69,14 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id) | |||
| 67 | Common::HexArrayToString(nca_id, false))); | 69 | Common::HexArrayToString(nca_id, false))); |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | Loader::ResultStatus NAX::Parse(std::string path) { | 72 | Loader::ResultStatus NAX::Parse(std::string_view path) { |
| 71 | if (file->ReadObject(header.get()) != sizeof(NAXHeader)) | 73 | if (file->ReadObject(header.get()) != sizeof(NAXHeader)) |
| 72 | return Loader::ResultStatus::ErrorBadNAXHeader; | 74 | return Loader::ResultStatus::ErrorBadNAXHeader; |
| 73 | 75 | ||
| 74 | if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) | 76 | if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) |
| 75 | return Loader::ResultStatus::ErrorBadNAXHeader; | 77 | return Loader::ResultStatus::ErrorBadNAXHeader; |
| 76 | 78 | ||
| 77 | if (file->GetSize() < 0x4000 + header->file_size) | 79 | if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) |
| 78 | return Loader::ResultStatus::ErrorIncorrectNAXFileSize; | 80 | return Loader::ResultStatus::ErrorIncorrectNAXFileSize; |
| 79 | 81 | ||
| 80 | keys.DeriveSDSeedLazy(); | 82 | keys.DeriveSDSeedLazy(); |
| @@ -87,14 +89,14 @@ Loader::ResultStatus NAX::Parse(std::string path) { | |||
| 87 | const auto enc_keys = header->key_area; | 89 | const auto enc_keys = header->key_area; |
| 88 | 90 | ||
| 89 | size_t i = 0; | 91 | size_t i = 0; |
| 90 | for (; i < 2; ++i) { | 92 | for (; i < sd_keys.size(); ++i) { |
| 91 | std::array<Core::Crypto::Key128, 2> nax_keys{}; | 93 | std::array<Core::Crypto::Key128, 2> nax_keys{}; |
| 92 | if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, path.c_str(), | 94 | if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, std::string(path).c_str(), |
| 93 | path.size())) { | 95 | path.size())) { |
| 94 | return Loader::ResultStatus::ErrorNAXKeyHMACFailed; | 96 | return Loader::ResultStatus::ErrorNAXKeyHMACFailed; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | for (size_t j = 0; j < 2; ++j) { | 99 | for (size_t j = 0; j < nax_keys.size(); ++j) { |
| 98 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(nax_keys[j], | 100 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(nax_keys[j], |
| 99 | Core::Crypto::Mode::ECB); | 101 | Core::Crypto::Mode::ECB); |
| 100 | cipher.Transcode(enc_keys[j].data(), 0x10, header->key_area[j].data(), | 102 | cipher.Transcode(enc_keys[j].data(), 0x10, header->key_area[j].data(), |
| @@ -117,28 +119,29 @@ Loader::ResultStatus NAX::Parse(std::string path) { | |||
| 117 | type = static_cast<NAXContentType>(i); | 119 | type = static_cast<NAXContentType>(i); |
| 118 | 120 | ||
| 119 | Core::Crypto::Key256 final_key{}; | 121 | Core::Crypto::Key256 final_key{}; |
| 120 | memcpy(final_key.data(), &header->key_area, 0x20); | 122 | std::memcpy(final_key.data(), &header->key_area, final_key.size()); |
| 121 | const auto enc_file = std::make_shared<OffsetVfsFile>(file, header->file_size, 0x4000); | 123 | const auto enc_file = |
| 124 | std::make_shared<OffsetVfsFile>(file, header->file_size, NAX_HEADER_PADDING_SIZE); | ||
| 122 | dec_file = std::make_shared<Core::Crypto::XTSEncryptionLayer>(enc_file, final_key); | 125 | dec_file = std::make_shared<Core::Crypto::XTSEncryptionLayer>(enc_file, final_key); |
| 123 | 126 | ||
| 124 | return Loader::ResultStatus::Success; | 127 | return Loader::ResultStatus::Success; |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | Loader::ResultStatus NAX::GetStatus() { | 130 | Loader::ResultStatus NAX::GetStatus() const { |
| 128 | return status; | 131 | return status; |
| 129 | } | 132 | } |
| 130 | 133 | ||
| 131 | VirtualFile NAX::GetDecrypted() { | 134 | VirtualFile NAX::GetDecrypted() const { |
| 132 | return dec_file; | 135 | return dec_file; |
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | std::shared_ptr<NCA> NAX::AsNCA() { | 138 | std::shared_ptr<NCA> NAX::AsNCA() const { |
| 136 | if (type == NAXContentType::NCA) | 139 | if (type == NAXContentType::NCA) |
| 137 | return std::make_shared<NCA>(GetDecrypted()); | 140 | return std::make_shared<NCA>(GetDecrypted()); |
| 138 | return nullptr; | 141 | return nullptr; |
| 139 | } | 142 | } |
| 140 | 143 | ||
| 141 | NAXContentType NAX::GetContentType() { | 144 | NAXContentType NAX::GetContentType() const { |
| 142 | return type; | 145 | return type; |
| 143 | } | 146 | } |
| 144 | 147 | ||
diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h index 4e44f634a..5249ad026 100644 --- a/src/core/file_sys/xts_archive.h +++ b/src/core/file_sys/xts_archive.h | |||
| @@ -33,13 +33,13 @@ public: | |||
| 33 | explicit NAX(VirtualFile file); | 33 | explicit NAX(VirtualFile file); |
| 34 | explicit NAX(VirtualFile file, std::array<u8, 0x10> nca_id); | 34 | explicit NAX(VirtualFile file, std::array<u8, 0x10> nca_id); |
| 35 | 35 | ||
| 36 | Loader::ResultStatus GetStatus(); | 36 | Loader::ResultStatus GetStatus() const; |
| 37 | 37 | ||
| 38 | VirtualFile GetDecrypted(); | 38 | VirtualFile GetDecrypted() const; |
| 39 | 39 | ||
| 40 | std::shared_ptr<NCA> AsNCA(); | 40 | std::shared_ptr<NCA> AsNCA() const; |
| 41 | 41 | ||
| 42 | NAXContentType GetContentType(); | 42 | NAXContentType GetContentType() const; |
| 43 | 43 | ||
| 44 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | 44 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; |
| 45 | 45 | ||
| @@ -53,7 +53,7 @@ protected: | |||
| 53 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 53 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
| 54 | 54 | ||
| 55 | private: | 55 | private: |
| 56 | Loader::ResultStatus Parse(std::string path); | 56 | Loader::ResultStatus Parse(std::string_view path); |
| 57 | 57 | ||
| 58 | std::unique_ptr<NAXHeader> header; | 58 | std::unique_ptr<NAXHeader> header; |
| 59 | 59 | ||