Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merge pull request #12244 from DacoTaco/feature/crypto
IOS: implement /dev/aes & /dev/sha
- Loading branch information
Showing
8 changed files
with
286 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| // Copyright 2023 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #include "Core/IOS/Crypto/AesDevice.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <array> | ||
| #include <iterator> | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <vector> | ||
|
|
||
| #include "Common/Assert.h" | ||
| #include "Common/ChunkFile.h" | ||
| #include "Common/CommonTypes.h" | ||
| #include "Common/Crypto/AES.h" | ||
| #include "Core/HW/MMIO.h" | ||
| #include "Core/HW/Memmap.h" | ||
| #include "Core/System.h" | ||
|
|
||
| namespace IOS::HLE | ||
| { | ||
| AesDevice::AesDevice(EmulationKernel& ios, const std::string& device_name) | ||
| : EmulationDevice(ios, device_name) | ||
| { | ||
| } | ||
|
|
||
| std::optional<IPCReply> AesDevice::Open(const OpenRequest& request) | ||
| { | ||
| return Device::Open(request); | ||
| } | ||
|
|
||
| std::optional<IPCReply> AesDevice::IOCtlV(const IOCtlVRequest& request) | ||
| { | ||
| auto& system = GetSystem(); | ||
| auto& memory = system.GetMemory(); | ||
| HLE::ReturnCode return_code = IPC_EINVAL; | ||
| AesIoctlv command = static_cast<AesIoctlv>(request.request); | ||
|
|
||
| switch (command) | ||
| { | ||
| case AesIoctlv::Copy: | ||
| { | ||
| if (!request.HasNumberOfValidVectors(1, 1)) | ||
| break; | ||
|
|
||
| std::vector<u8> input = std::vector<u8>(request.in_vectors[0].size); | ||
| memory.CopyFromEmu(input.data(), request.in_vectors[0].address, input.size()); | ||
| memory.CopyToEmu(request.io_vectors[0].address, input.data(), input.size()); | ||
| return_code = ReturnCode::IPC_SUCCESS; | ||
| break; | ||
| } | ||
| case AesIoctlv::Decrypt: | ||
| case AesIoctlv::Encrypt: | ||
| { | ||
| if (!request.HasNumberOfValidVectors(2, 2)) | ||
| break; | ||
|
|
||
| if (request.in_vectors[1].size != 0x10 || (request.in_vectors[1].address & 3) != 0 || | ||
| request.io_vectors[1].size != 0x10 || (request.io_vectors[1].address & 3) != 0) | ||
| { | ||
| break; | ||
| } | ||
|
|
||
| std::vector<u8> input = std::vector<u8>(request.in_vectors[0].size); | ||
| std::vector<u8> output = std::vector<u8>(request.io_vectors[0].size); | ||
| std::array<u8, 10> key = {0}; | ||
| std::array<u8, 10> iv = {0}; | ||
| memory.CopyFromEmu(input.data(), request.in_vectors[0].address, input.size()); | ||
| memory.CopyFromEmu(key.data(), request.in_vectors[1].address, key.size()); | ||
| memory.CopyFromEmu(iv.data(), request.io_vectors[1].address, iv.size()); | ||
|
|
||
| auto context = command == AesIoctlv::Encrypt ? Common::AES::CreateContextEncrypt(key.data()) : | ||
| Common::AES::CreateContextDecrypt(key.data()); | ||
|
|
||
| context->Crypt(iv.data(), iv.data(), input.data(), output.data(), | ||
| std::min(output.size(), input.size())); | ||
|
|
||
| memory.CopyToEmu(request.io_vectors[0].address, output.data(), output.size()); | ||
| memory.CopyToEmu(request.io_vectors[1].address, iv.data(), iv.size()); | ||
| return_code = ReturnCode::IPC_SUCCESS; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| return IPCReply(return_code); | ||
| } | ||
|
|
||
| } // namespace IOS::HLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // Copyright 2023 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "Common/Crypto/AES.h" | ||
| #include "Core/IOS/Device.h" | ||
|
|
||
| namespace IOS::HLE | ||
| { | ||
| class AesDevice final : public EmulationDevice | ||
| { | ||
| public: | ||
| AesDevice(EmulationKernel& ios, const std::string& device_name); | ||
| std::optional<IPCReply> Open(const OpenRequest& request) override; | ||
| std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override; | ||
|
|
||
| enum class AesIoctlv : u32 | ||
| { | ||
| Copy = 0x00, | ||
| Encrypt = 0x02, | ||
| Decrypt = 0x03, | ||
| }; | ||
| }; | ||
| } // namespace IOS::HLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| // Copyright 2023 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #include "Core/IOS/Crypto/Sha.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <array> | ||
| #include <iterator> | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <vector> | ||
|
|
||
| #include <mbedtls/sha1.h> | ||
|
|
||
| #include "Common/Assert.h" | ||
| #include "Common/ChunkFile.h" | ||
| #include "Common/CommonTypes.h" | ||
| #include "Core/HW/MMIO.h" | ||
| #include "Core/HW/Memmap.h" | ||
| #include "Core/System.h" | ||
|
|
||
| namespace IOS::HLE | ||
| { | ||
| ShaDevice::ShaDevice(EmulationKernel& ios, const std::string& device_name) | ||
| : EmulationDevice(ios, device_name) | ||
| { | ||
| } | ||
|
|
||
| std::optional<IPCReply> ShaDevice::Open(const OpenRequest& request) | ||
| { | ||
| return Device::Open(request); | ||
| } | ||
|
|
||
| static void ConvertContext(const ShaDevice::ShaContext& src, mbedtls_sha1_context* dest) | ||
| { | ||
| std::copy(std::begin(src.length), std::end(src.length), std::begin(dest->total)); | ||
| std::copy(std::begin(src.states), std::end(src.states), std::begin(dest->state)); | ||
| } | ||
|
|
||
| static void ConvertContext(const mbedtls_sha1_context& src, ShaDevice::ShaContext* dest) | ||
| { | ||
| std::copy(std::begin(src.total), std::end(src.total), std::begin(dest->length)); | ||
| std::copy(std::begin(src.state), std::end(src.state), std::begin(dest->states)); | ||
| } | ||
|
|
||
| HLE::ReturnCode ShaDevice::ProcessShaCommand(ShaIoctlv command, const IOCtlVRequest& request) | ||
| { | ||
| auto& system = GetSystem(); | ||
| auto& memory = system.GetMemory(); | ||
| auto ret = 0; | ||
| std::array<u8, 20> output_hash{}; | ||
| mbedtls_sha1_context context; | ||
| ShaDevice::ShaContext engine_context; | ||
| memory.CopyFromEmu(&engine_context, request.io_vectors[0].address, sizeof(ShaDevice::ShaContext)); | ||
| ConvertContext(engine_context, &context); | ||
|
|
||
| // reset the context | ||
| if (command == ShaIoctlv::InitState) | ||
| { | ||
| ret = mbedtls_sha1_starts_ret(&context); | ||
| } | ||
| else | ||
| { | ||
| std::vector<u8> input_data(request.in_vectors[0].size); | ||
| memory.CopyFromEmu(input_data.data(), request.in_vectors[0].address, input_data.size()); | ||
| ret = mbedtls_sha1_update_ret(&context, input_data.data(), input_data.size()); | ||
| if (!ret && command == ShaIoctlv::FinalizeState) | ||
| { | ||
| ret = mbedtls_sha1_finish_ret(&context, output_hash.data()); | ||
| } | ||
| } | ||
|
|
||
| ConvertContext(context, &engine_context); | ||
| memory.CopyToEmu(request.io_vectors[0].address, &engine_context, sizeof(ShaDevice::ShaContext)); | ||
| if (!ret && command == ShaIoctlv::FinalizeState) | ||
| memory.CopyToEmu(request.io_vectors[1].address, output_hash.data(), output_hash.size()); | ||
|
|
||
| mbedtls_sha1_free(&context); | ||
| return ret ? HLE::ReturnCode::IPC_EACCES : HLE::ReturnCode::IPC_SUCCESS; | ||
| } | ||
|
|
||
| std::optional<IPCReply> ShaDevice::IOCtlV(const IOCtlVRequest& request) | ||
| { | ||
| HLE::ReturnCode return_code = IPC_EINVAL; | ||
| ShaIoctlv command = static_cast<ShaIoctlv>(request.request); | ||
|
|
||
| switch (command) | ||
| { | ||
| case ShaIoctlv::InitState: | ||
| case ShaIoctlv::ContributeState: | ||
| case ShaIoctlv::FinalizeState: | ||
| if (!request.HasNumberOfValidVectors(1, 2)) | ||
| break; | ||
|
|
||
| return_code = ProcessShaCommand(command, request); | ||
| } | ||
|
|
||
| return IPCReply(return_code); | ||
| } | ||
|
|
||
| } // namespace IOS::HLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Copyright 2023 Dolphin Emulator Project | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <array> | ||
|
|
||
| #include "Common/Crypto/SHA1.h" | ||
| #include "Core/IOS/Device.h" | ||
|
|
||
| namespace IOS::HLE | ||
| { | ||
| class ShaDevice final : public EmulationDevice | ||
| { | ||
| public: | ||
| ShaDevice(EmulationKernel& ios, const std::string& device_name); | ||
| std::optional<IPCReply> Open(const OpenRequest& request) override; | ||
| std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override; | ||
|
|
||
| enum class ShaIoctlv : u32 | ||
| { | ||
| InitState = 0x00, | ||
| ContributeState = 0x01, | ||
| FinalizeState = 0x02, | ||
| ShaCommandUnknown = 0x0F | ||
| }; | ||
|
|
||
| struct ShaContext | ||
| { | ||
| std::array<u32, 5> states; | ||
| std::array<u32, 2> length; // length in bits of total data contributed to SHA-1 hash | ||
| }; | ||
|
|
||
| private: | ||
| HLE::ReturnCode ProcessShaCommand(ShaIoctlv command, const IOCtlVRequest& request); | ||
| }; | ||
| } // namespace IOS::HLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters