A tool for deriving PKG packet encryption keys for ps4 written in c++
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | |
| 4 | #include <thread> |
| 5 | #include "common/rdtsc.h" |
| 6 | #include "common/uint128.h" |
| 7 | |
| 8 | #ifdef _WIN64 |
| 9 | #include <windows.h> |
| 10 | #endif |
| 11 | |
| 12 | namespace Common { |
| 13 | |
| 14 | static constexpr size_t SecondToNanoseconds = 1000000000ULL; |
| 15 | |
| 16 | template <u64 Nearest> |
| 17 | static u64 RoundToNearest(u64 value) { |
| 18 | const auto mod = value % Nearest; |
| 19 | return mod >= (Nearest / 2) ? (value - mod + Nearest) : (value - mod); |
| 20 | } |
| 21 | |
| 22 | static u64 GetTimeNs() { |
| 23 | #ifdef _WIN64 |
| 24 | // GetSystemTimePreciseAsFileTime returns the file time in 100ns units. |
| 25 | static constexpr u64 Multiplier = 100; |
| 26 | // Convert Windows epoch to Unix epoch. |
| 27 | static constexpr u64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL; |
| 28 | FILETIME filetime; |
| 29 | GetSystemTimePreciseAsFileTime(&filetime); |
| 30 | return Multiplier * ((static_cast<u64>(filetime.dwHighDateTime) << 32) + |
| 31 | static_cast<u64>(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch); |
| 32 | #elif defined(__APPLE__) |
| 33 | return clock_gettime_nsec_np(CLOCK_REALTIME); |
| 34 | #else |
| 35 | timespec ts; |
| 36 | clock_gettime(CLOCK_REALTIME, &ts); |
| 37 | return ts.tv_sec * SecondToNanoseconds + ts.tv_nsec; |
| 38 | #endif |
| 39 | } |
| 40 | |
| 41 | u64 EstimateRDTSCFrequency() { |
| 42 | // Discard the first result measuring the rdtsc. |
| 43 | FencedRDTSC(); |
| 44 | std::this_thread::sleep_for(std::chrono::milliseconds{1}); |
| 45 | FencedRDTSC(); |
| 46 | |
| 47 | // Get the current time. |
| 48 | const auto start_time = GetTimeNs(); |
| 49 | const u64 tsc_start = FencedRDTSC(); |
| 50 | // Wait for 100 milliseconds. |
| 51 | std::this_thread::sleep_for(std::chrono::milliseconds{100}); |
| 52 | const auto end_time = GetTimeNs(); |
| 53 | const u64 tsc_end = FencedRDTSC(); |
| 54 | // Calculate differences. |
| 55 | const u64 tsc_diff = tsc_end - tsc_start; |
| 56 | const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, end_time - start_time); |
| 57 | return RoundToNearest<100'000>(tsc_freq); |
| 58 | } |
| 59 | |
| 60 | } // namespace Common |
| 61 |