Reimplement GetPseudoDeviceId to be more accurate

Now returns a valid V5 UUID and uses the game's seed from control.nacp
for generation.
This commit is contained in:
Billy Laws 2021-05-27 22:25:19 +01:00
parent d4b13c34ee
commit 6f9189e8f9
5 changed files with 35 additions and 4 deletions

View File

@ -74,4 +74,18 @@ namespace skyline {
return uuid.Swap(); return uuid.Swap();
} }
UUID UUID::GenerateUuidV5(const std::array<u8, 20> sha1) {
constexpr u8 reserved{0x1}; // RFC4122 variant
constexpr u8 version{0x5}; // v4 UUIDs are generated using SHA1 hashes
UuidLayout uuid;
std::memcpy(&uuid, sha1.data(), sizeof(UuidLayout));
// Set format bits
uuid.reserved = reserved;
uuid.version = version;
return uuid.Swap();
}
} }

View File

@ -15,6 +15,11 @@ namespace skyline {
*/ */
static UUID GenerateUuidV4(); static UUID GenerateUuidV4();
/**
* @brief Generates a version 5 UUID from the given SHA1
*/
static UUID GenerateUuidV5(const std::array<u8, 20> sha1);
/** /**
* @brief Checks if a UUID is an invalid nil UUID * @brief Checks if a UUID is an invalid nil UUID
*/ */

View File

@ -1,6 +1,9 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <common/uuid.h>
#include <mbedtls/sha1.h>
#include <loader/loader.h>
#include <kernel/types/KProcess.h> #include <kernel/types/KProcess.h>
#include <services/account/IAccountServiceForApplication.h> #include <services/account/IAccountServiceForApplication.h>
#include <services/am/storage/IStorage.h> #include <services/am/storage/IStorage.h>
@ -39,8 +42,15 @@ namespace skyline::service::am {
} }
Result IApplicationFunctions::GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { Result IApplicationFunctions::GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<u64>(0L); auto seedForPseudoDeviceId{state.loader->nacp->nacpContents.seedForPseudoDeviceId};
response.Push<u64>(0L); std::array<u8, 20> hashBuf{};
// On HOS the seed from control.ncap is hashed together with the device specific device ID seed,
// for us it's enough to just hash the seed from control.nacp as it provides the same guarantees.
if (int err{mbedtls_sha1_ret(seedForPseudoDeviceId.data(), seedForPseudoDeviceId.size(), hashBuf.data())}; err < 0)
throw exception("Failed to hash device ID, err: {}", err);
response.Push<UUID>(UUID::GenerateUuidV5(hashBuf));
return {}; return {};
} }

View File

@ -43,7 +43,7 @@ namespace skyline::service::am {
Result NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns a UUID, however what it refers to is currently unknown * @brief Returns a V5 UUID generated from a seed in control.nacp and a device specific seed
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId * @url https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId
*/ */
Result GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -26,7 +26,9 @@ namespace skyline::vfs {
std::array<ApplicationTitle, 0x10> titleEntries; //!< Title entries for each language std::array<ApplicationTitle, 0x10> titleEntries; //!< Title entries for each language
u8 _pad0_[0x78]; u8 _pad0_[0x78];
u64 saveDataOwnerId; //!< The ID that should be used for this application's savedata u64 saveDataOwnerId; //!< The ID that should be used for this application's savedata
u8 _pad1_[0xF80]; u8 _pad1_[0x78];
std::array<u8, 8> seedForPseudoDeviceId; //!< Seed that is combined with the device seed for generating the pseudo-device ID
u8 _pad2_[0xF00];
} nacpContents{}; } nacpContents{};
static_assert(sizeof(NacpData) == 0x4000); static_assert(sizeof(NacpData) == 0x4000);