diff options
| author | 2020-08-05 22:35:41 -0400 | |
|---|---|---|
| committer | 2020-08-05 22:35:41 -0400 | |
| commit | 35c1607f231cab060305e79f434ef15442c162f1 (patch) | |
| tree | 0a2af713d7f5ca2b0c0bbe45176c112ae9ba2b03 | |
| parent | Merge pull request #4477 from lioncash/log-desig (diff) | |
| parent | aes_util: Allow SetIV to be non-allocating (diff) | |
| download | yuzu-35c1607f231cab060305e79f434ef15442c162f1.tar.gz yuzu-35c1607f231cab060305e79f434ef15442c162f1.tar.xz yuzu-35c1607f231cab060305e79f434ef15442c162f1.zip | |
Merge pull request #4484 from lioncash/aesutil
aes_util: Allow SetIV() to be non-allocating
Diffstat (limited to '')
| -rw-r--r-- | src/core/crypto/aes_util.cpp | 21 | ||||
| -rw-r--r-- | src/core/crypto/aes_util.h | 9 | ||||
| -rw-r--r-- | src/core/crypto/ctr_encryption_layer.cpp | 9 | ||||
| -rw-r--r-- | src/core/crypto/ctr_encryption_layer.h | 9 | ||||
| -rw-r--r-- | src/core/crypto/partition_data_manager.cpp | 5 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 7 | ||||
| -rw-r--r-- | src/core/file_sys/nca_patch.cpp | 3 |
7 files changed, 36 insertions, 27 deletions
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp index 4be76bb43..330996b24 100644 --- a/src/core/crypto/aes_util.cpp +++ b/src/core/crypto/aes_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | ||
| 5 | #include <mbedtls/cipher.h> | 6 | #include <mbedtls/cipher.h> |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| @@ -10,8 +11,10 @@ | |||
| 10 | 11 | ||
| 11 | namespace Core::Crypto { | 12 | namespace Core::Crypto { |
| 12 | namespace { | 13 | namespace { |
| 13 | std::vector<u8> CalculateNintendoTweak(std::size_t sector_id) { | 14 | using NintendoTweak = std::array<u8, 16>; |
| 14 | std::vector<u8> out(0x10); | 15 | |
| 16 | NintendoTweak CalculateNintendoTweak(std::size_t sector_id) { | ||
| 17 | NintendoTweak out{}; | ||
| 15 | for (std::size_t i = 0xF; i <= 0xF; --i) { | 18 | for (std::size_t i = 0xF; i <= 0xF; --i) { |
| 16 | out[i] = sector_id & 0xFF; | 19 | out[i] = sector_id & 0xFF; |
| 17 | sector_id >>= 8; | 20 | sector_id >>= 8; |
| @@ -64,13 +67,6 @@ AESCipher<Key, KeySize>::~AESCipher() { | |||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | template <typename Key, std::size_t KeySize> | 69 | template <typename Key, std::size_t KeySize> |
| 67 | void AESCipher<Key, KeySize>::SetIV(std::vector<u8> iv) { | ||
| 68 | ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, iv.data(), iv.size()) || | ||
| 69 | mbedtls_cipher_set_iv(&ctx->decryption_context, iv.data(), iv.size())) == 0, | ||
| 70 | "Failed to set IV on mbedtls ciphers."); | ||
| 71 | } | ||
| 72 | |||
| 73 | template <typename Key, std::size_t KeySize> | ||
| 74 | void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { | 70 | void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const { |
| 75 | auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context; | 71 | auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context; |
| 76 | 72 | ||
| @@ -124,6 +120,13 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, std::size_t size, u8* | |||
| 124 | } | 120 | } |
| 125 | } | 121 | } |
| 126 | 122 | ||
| 123 | template <typename Key, std::size_t KeySize> | ||
| 124 | void AESCipher<Key, KeySize>::SetIVImpl(const u8* data, std::size_t size) { | ||
| 125 | ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data, size) || | ||
| 126 | mbedtls_cipher_set_iv(&ctx->decryption_context, data, size)) == 0, | ||
| 127 | "Failed to set IV on mbedtls ciphers."); | ||
| 128 | } | ||
| 129 | |||
| 127 | template class AESCipher<Key128>; | 130 | template class AESCipher<Key128>; |
| 128 | template class AESCipher<Key256>; | 131 | template class AESCipher<Key256>; |
| 129 | } // namespace Core::Crypto | 132 | } // namespace Core::Crypto |
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h index edc4ab910..e2a304186 100644 --- a/src/core/crypto/aes_util.h +++ b/src/core/crypto/aes_util.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <type_traits> | 8 | #include <type_traits> |
| 9 | #include <vector> | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 11 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/vfs.h" |
| 12 | 11 | ||
| @@ -32,10 +31,12 @@ class AESCipher { | |||
| 32 | 31 | ||
| 33 | public: | 32 | public: |
| 34 | AESCipher(Key key, Mode mode); | 33 | AESCipher(Key key, Mode mode); |
| 35 | |||
| 36 | ~AESCipher(); | 34 | ~AESCipher(); |
| 37 | 35 | ||
| 38 | void SetIV(std::vector<u8> iv); | 36 | template <typename ContiguousContainer> |
| 37 | void SetIV(const ContiguousContainer& container) { | ||
| 38 | SetIVImpl(std::data(container), std::size(container)); | ||
| 39 | } | ||
| 39 | 40 | ||
| 40 | template <typename Source, typename Dest> | 41 | template <typename Source, typename Dest> |
| 41 | void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const { | 42 | void Transcode(const Source* src, std::size_t size, Dest* dest, Op op) const { |
| @@ -59,6 +60,8 @@ public: | |||
| 59 | std::size_t sector_size, Op op); | 60 | std::size_t sector_size, Op op); |
| 60 | 61 | ||
| 61 | private: | 62 | private: |
| 63 | void SetIVImpl(const u8* data, std::size_t size); | ||
| 64 | |||
| 62 | std::unique_ptr<CipherContext> ctx; | 65 | std::unique_ptr<CipherContext> ctx; |
| 63 | }; | 66 | }; |
| 64 | } // namespace Core::Crypto | 67 | } // namespace Core::Crypto |
diff --git a/src/core/crypto/ctr_encryption_layer.cpp b/src/core/crypto/ctr_encryption_layer.cpp index 902841c77..5c84bb0a4 100644 --- a/src/core/crypto/ctr_encryption_layer.cpp +++ b/src/core/crypto/ctr_encryption_layer.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "core/crypto/ctr_encryption_layer.h" | 8 | #include "core/crypto/ctr_encryption_layer.h" |
| @@ -10,8 +11,7 @@ namespace Core::Crypto { | |||
| 10 | 11 | ||
| 11 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, | 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, |
| 12 | std::size_t base_offset) | 13 | std::size_t base_offset) |
| 13 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR), | 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR) {} |
| 14 | iv(16, 0) {} | ||
| 15 | 15 | ||
| 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { | 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 17 | if (length == 0) | 17 | if (length == 0) |
| @@ -39,9 +39,8 @@ std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t o | |||
| 39 | return read + Read(data + read, length - read, offset + read); | 39 | return read + Read(data + read, length - read, offset + read); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | void CTREncryptionLayer::SetIV(const std::vector<u8>& iv_) { | 42 | void CTREncryptionLayer::SetIV(const IVData& iv_) { |
| 43 | const auto length = std::min(iv_.size(), iv.size()); | 43 | iv = iv_; |
| 44 | iv.assign(iv_.cbegin(), iv_.cbegin() + length); | ||
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | void CTREncryptionLayer::UpdateIV(std::size_t offset) const { | 46 | void CTREncryptionLayer::UpdateIV(std::size_t offset) const { |
diff --git a/src/core/crypto/ctr_encryption_layer.h b/src/core/crypto/ctr_encryption_layer.h index a7bf810f4..a2429f001 100644 --- a/src/core/crypto/ctr_encryption_layer.h +++ b/src/core/crypto/ctr_encryption_layer.h | |||
| @@ -4,7 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | 7 | #include <array> |
| 8 | |||
| 8 | #include "core/crypto/aes_util.h" | 9 | #include "core/crypto/aes_util.h" |
| 9 | #include "core/crypto/encryption_layer.h" | 10 | #include "core/crypto/encryption_layer.h" |
| 10 | #include "core/crypto/key_manager.h" | 11 | #include "core/crypto/key_manager.h" |
| @@ -14,18 +15,20 @@ namespace Core::Crypto { | |||
| 14 | // Sits on top of a VirtualFile and provides CTR-mode AES decription. | 15 | // Sits on top of a VirtualFile and provides CTR-mode AES decription. |
| 15 | class CTREncryptionLayer : public EncryptionLayer { | 16 | class CTREncryptionLayer : public EncryptionLayer { |
| 16 | public: | 17 | public: |
| 18 | using IVData = std::array<u8, 16>; | ||
| 19 | |||
| 17 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); | 20 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); |
| 18 | 21 | ||
| 19 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; | 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; |
| 20 | 23 | ||
| 21 | void SetIV(const std::vector<u8>& iv); | 24 | void SetIV(const IVData& iv); |
| 22 | 25 | ||
| 23 | private: | 26 | private: |
| 24 | std::size_t base_offset; | 27 | std::size_t base_offset; |
| 25 | 28 | ||
| 26 | // Must be mutable as operations modify cipher contexts. | 29 | // Must be mutable as operations modify cipher contexts. |
| 27 | mutable AESCipher<Key128> cipher; | 30 | mutable AESCipher<Key128> cipher; |
| 28 | mutable std::vector<u8> iv; | 31 | mutable IVData iv{}; |
| 29 | 32 | ||
| 30 | void UpdateIV(std::size_t offset) const; | 33 | void UpdateIV(std::size_t offset) const; |
| 31 | }; | 34 | }; |
diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 7ed71ac3a..b31a81560 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp | |||
| @@ -346,10 +346,9 @@ FileSys::VirtualFile PartitionDataManager::GetPackage2Raw(Package2Type type) con | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | static bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) { | 348 | static bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) { |
| 349 | const std::vector<u8> iv(header.header_ctr.begin(), header.header_ctr.end()); | ||
| 350 | Package2Header temp = header; | 349 | Package2Header temp = header; |
| 351 | AESCipher<Key128> cipher(key, Mode::CTR); | 350 | AESCipher<Key128> cipher(key, Mode::CTR); |
| 352 | cipher.SetIV(iv); | 351 | cipher.SetIV(header.header_ctr); |
| 353 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr, | 352 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr, |
| 354 | Op::Decrypt); | 353 | Op::Decrypt); |
| 355 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { | 354 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { |
| @@ -388,7 +387,7 @@ void PartitionDataManager::DecryptPackage2(const std::array<Key128, 0x20>& packa | |||
| 388 | auto c = a->ReadAllBytes(); | 387 | auto c = a->ReadAllBytes(); |
| 389 | 388 | ||
| 390 | AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR); | 389 | AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR); |
| 391 | cipher.SetIV({header.section_ctr[1].begin(), header.section_ctr[1].end()}); | 390 | cipher.SetIV(header.section_ctr[1]); |
| 392 | cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); | 391 | cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); |
| 393 | 392 | ||
| 394 | const auto ini_file = std::make_shared<FileSys::VectorVfsFile>(c); | 393 | const auto ini_file = std::make_shared<FileSys::VectorVfsFile>(c); |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 473245d5a..5039341c7 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -495,9 +495,10 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s | |||
| 495 | 495 | ||
| 496 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key, | 496 | auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key, |
| 497 | starting_offset); | 497 | starting_offset); |
| 498 | std::vector<u8> iv(16); | 498 | Core::Crypto::CTREncryptionLayer::IVData iv{}; |
| 499 | for (u8 i = 0; i < 8; ++i) | 499 | for (std::size_t i = 0; i < 8; ++i) { |
| 500 | iv[i] = s_header.raw.section_ctr[0x8 - i - 1]; | 500 | iv[i] = s_header.raw.section_ctr[8 - i - 1]; |
| 501 | } | ||
| 501 | out->SetIV(iv); | 502 | out->SetIV(iv); |
| 502 | return std::static_pointer_cast<VfsFile>(out); | 503 | return std::static_pointer_cast<VfsFile>(out); |
| 503 | } | 504 | } |
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index 0090cc6c4..fe7375e84 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 6 | #include <cstddef> | 7 | #include <cstddef> |
| 7 | #include <cstring> | 8 | #include <cstring> |
| 8 | 9 | ||
| @@ -66,7 +67,7 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { | |||
| 66 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); | 67 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); |
| 67 | 68 | ||
| 68 | // Calculate AES IV | 69 | // Calculate AES IV |
| 69 | std::vector<u8> iv(16); | 70 | std::array<u8, 16> iv{}; |
| 70 | auto subsection_ctr = subsection.ctr; | 71 | auto subsection_ctr = subsection.ctr; |
| 71 | auto offset_iv = section_offset + base_offset; | 72 | auto offset_iv = section_offset + base_offset; |
| 72 | for (std::size_t i = 0; i < section_ctr.size(); ++i) | 73 | for (std::size_t i = 0; i < section_ctr.size(); ++i) |