IOS: implement /dev/sha

This commit is contained in:
DacoTaco 2023-10-18 21:48:19 +02:00
parent 2677fd9a8e
commit d4c18f3f31
6 changed files with 164 additions and 2 deletions

View file

@ -336,6 +336,8 @@ add_library(core
IOS/Device.h
IOS/DeviceStub.cpp
IOS/DeviceStub.h
IOS/Crypto/Sha.cpp
IOS/Crypto/Sha.h
IOS/DI/DI.cpp
IOS/DI/DI.h
IOS/DolphinDevice.cpp

View file

@ -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

View file

@ -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

View file

@ -28,6 +28,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/Crypto/Sha.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/DeviceStub.h"
@ -333,6 +334,8 @@ EmulationKernel::EmulationKernel(Core::System& system, u64 title_id)
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
ASSERT(m_fs);
AddDevice(std::make_unique<ShaDevice>(*this, "/dev/sha"));
m_fs_core = std::make_unique<FSCore>(*this);
AddDevice(std::make_unique<FSDevice>(*this, *m_fs_core, "/dev/fs"));
@ -649,6 +652,20 @@ std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device
return iterator != m_device_map.end() ? iterator->second : nullptr;
}
std::shared_ptr<Device> EmulationKernel::GetDeviceByFileDescriptor(const int fd)
{
if (fd < IPC_MAX_FDS)
return m_fdmap[fd];
switch (fd)
{
case 0x10001:
return GetDeviceByName("/dev/sha");
default:
return nullptr;
}
}
// Returns the FD for the newly opened device (on success) or an error code.
std::optional<IPCReply> EmulationKernel::OpenDevice(OpenRequest& request)
{
@ -703,7 +720,7 @@ std::optional<IPCReply> EmulationKernel::HandleIPCCommand(const Request& request
return OpenDevice(open_request);
}
const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr;
const auto device = GetDeviceByFileDescriptor(request.fd);
if (!device)
return IPCReply{IPC_EINVAL, 550_tbticks};
@ -713,7 +730,9 @@ std::optional<IPCReply> EmulationKernel::HandleIPCCommand(const Request& request
switch (request.command)
{
case IPC_CMD_CLOSE:
m_fdmap[request.fd].reset();
// if the fd is not a special IOS FD, we need to reset it too
if (request.fd < IPC_MAX_FDS)
m_fdmap[request.fd].reset();
ret = device->Close(request.fd);
break;
case IPC_CMD_READ:

View file

@ -154,6 +154,7 @@ public:
// Get a resource manager by name.
// This only works for devices which are part of the device map.
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
std::shared_ptr<Device> GetDeviceByFileDescriptor(const int fd);
std::shared_ptr<FSDevice> GetFSDevice();
std::shared_ptr<ESDevice> GetESDevice();

View file

@ -343,6 +343,7 @@
<ClInclude Include="Core\HW\WiimoteReal\WiimoteReal.h" />
<ClInclude Include="Core\HW\WiiSave.h" />
<ClInclude Include="Core\HW\WiiSaveStructs.h" />
<ClInclude Include="Core\IOS\Crypto\Sha.h" />
<ClInclude Include="Core\IOS\Device.h" />
<ClInclude Include="Core\IOS\DeviceStub.h" />
<ClInclude Include="Core\IOS\DI\DI.h" />
@ -983,6 +984,7 @@
<ClCompile Include="Core\HW\WiimoteReal\IOWin.cpp" />
<ClCompile Include="Core\HW\WiimoteReal\WiimoteReal.cpp" />
<ClCompile Include="Core\HW\WiiSave.cpp" />
<ClCompile Include="Core\IOS\Crypto\Sha.cpp" />
<ClCompile Include="Core\IOS\Device.cpp" />
<ClCompile Include="Core\IOS\DeviceStub.cpp" />
<ClCompile Include="Core\IOS\DI\DI.cpp" />