Create a random console_unique_id (#2668)
* Create a random console_id when config save_file is created Added button in system config to refresh the console unique id * Moved the connect for the button from .ui file to constructor of ConfigureSystem * Added warning and info dialog Fixup: Make use of qt5 style connects, renamed the refresh button, removed some duplicate code, changed random device and moved all to the generate function * Changed the random generator to reflect what a real 3DS stores as console unique id Fixup: Changed the warning message * Fixup: Set and Create * Fixup: Added console id label, therfore removed second message box * Fixup: fixed the endianess * Fixup: more endianness fixes * Fixup: Endianness the 3rd
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include "citra_qt/configuration/configure_system.h"
 | 
			
		||||
#include "citra_qt/ui_settings.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
@@ -15,8 +16,11 @@ static const std::array<int, 12> days_in_month = {{
 | 
			
		||||
 | 
			
		||||
ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) {
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
    connect(ui->combo_birthmonth, SIGNAL(currentIndexChanged(int)),
 | 
			
		||||
            SLOT(updateBirthdayComboBox(int)));
 | 
			
		||||
    connect(ui->combo_birthmonth,
 | 
			
		||||
            static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
 | 
			
		||||
            &ConfigureSystem::updateBirthdayComboBox);
 | 
			
		||||
    connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
 | 
			
		||||
            &ConfigureSystem::refreshConsoleID);
 | 
			
		||||
 | 
			
		||||
    this->setConfiguration();
 | 
			
		||||
}
 | 
			
		||||
@@ -71,6 +75,10 @@ void ConfigureSystem::ReadSystemSettings() {
 | 
			
		||||
    // set sound output mode
 | 
			
		||||
    sound_index = Service::CFG::GetSoundOutputMode();
 | 
			
		||||
    ui->combo_sound->setCurrentIndex(sound_index);
 | 
			
		||||
 | 
			
		||||
    // set the console id
 | 
			
		||||
    u64 console_id = Service::CFG::GetConsoleUniqueId();
 | 
			
		||||
    ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConfigureSystem::applyConfiguration() {
 | 
			
		||||
@@ -140,3 +148,21 @@ void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) {
 | 
			
		||||
    // restore the day selection
 | 
			
		||||
    ui->combo_birthday->setCurrentIndex(birthday_index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConfigureSystem::refreshConsoleID() {
 | 
			
		||||
    QMessageBox::StandardButton reply;
 | 
			
		||||
    QString warning_text = tr("This will replace your current virtual 3DS with a new one. "
 | 
			
		||||
                              "Your current virtual 3DS will not be recoverable. "
 | 
			
		||||
                              "This might have unexpected effects in games. This might fail, "
 | 
			
		||||
                              "if you use an outdated config savegame. Continue?");
 | 
			
		||||
    reply = QMessageBox::critical(this, tr("Warning"), warning_text,
 | 
			
		||||
                                  QMessageBox::No | QMessageBox::Yes);
 | 
			
		||||
    if (reply == QMessageBox::No)
 | 
			
		||||
        return;
 | 
			
		||||
    u32 random_number;
 | 
			
		||||
    u64 console_id;
 | 
			
		||||
    Service::CFG::GenerateConsoleUniqueId(random_number, console_id);
 | 
			
		||||
    Service::CFG::SetConsoleUniqueId(random_number, console_id);
 | 
			
		||||
    Service::CFG::UpdateConfigNANDSavegame();
 | 
			
		||||
    ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper());
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ public:
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void updateBirthdayComboBox(int birthmonth_index);
 | 
			
		||||
    void refreshConsoleID();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void ReadSystemSettings();
 | 
			
		||||
 
 | 
			
		||||
@@ -220,6 +220,29 @@
 | 
			
		||||
          </item>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item row="4" column="0">
 | 
			
		||||
         <widget class="QLabel" name="label_console_id">
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Console ID:</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item row="4" column="1">
 | 
			
		||||
         <widget class="QPushButton" name="button_regenerate_console_id">
 | 
			
		||||
          <property name="sizePolicy">
 | 
			
		||||
           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
 | 
			
		||||
            <horstretch>0</horstretch>
 | 
			
		||||
            <verstretch>0</verstretch>
 | 
			
		||||
           </sizepolicy>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="layoutDirection">
 | 
			
		||||
           <enum>Qt::RightToLeft</enum>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Regenerate</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
       </layout>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <cryptopp/osrng.h>
 | 
			
		||||
#include <cryptopp/sha.h>
 | 
			
		||||
#include "common/file_util.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
@@ -50,6 +51,7 @@ enum ConfigBlockID {
 | 
			
		||||
    SoundOutputModeBlockID = 0x00070001,
 | 
			
		||||
    ConsoleUniqueID1BlockID = 0x00090000,
 | 
			
		||||
    ConsoleUniqueID2BlockID = 0x00090001,
 | 
			
		||||
    ConsoleUniqueID3BlockID = 0x00090002,
 | 
			
		||||
    UsernameBlockID = 0x000A0000,
 | 
			
		||||
    BirthdayBlockID = 0x000A0001,
 | 
			
		||||
    LanguageBlockID = 0x000A0002,
 | 
			
		||||
@@ -86,7 +88,6 @@ struct ConsoleCountryInfo {
 | 
			
		||||
static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
 | 
			
		||||
static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}};
 | 
			
		||||
static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
 | 
			
		||||
static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0};
 | 
			
		||||
@@ -438,13 +439,22 @@ ResultCode FormatConfig() {
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
 | 
			
		||||
                              &CONSOLE_UNIQUE_ID);
 | 
			
		||||
    u32 random_number;
 | 
			
		||||
    u64 console_id;
 | 
			
		||||
    GenerateConsoleUniqueId(random_number, console_id);
 | 
			
		||||
 | 
			
		||||
    u64_le console_id_le = console_id;
 | 
			
		||||
    res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
 | 
			
		||||
                              &CONSOLE_UNIQUE_ID);
 | 
			
		||||
    res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    u32_le random_number_le = random_number;
 | 
			
		||||
    res = CreateConfigInfoBlk(ConsoleUniqueID3BlockID, sizeof(random_number_le), 0xE,
 | 
			
		||||
                              &random_number_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
@@ -663,5 +673,40 @@ SoundOutputMode GetSoundOutputMode() {
 | 
			
		||||
    return static_cast<SoundOutputMode>(block);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GenerateConsoleUniqueId(u32& random_number, u64& console_id) {
 | 
			
		||||
    CryptoPP::AutoSeededRandomPool rng;
 | 
			
		||||
    random_number = rng.GenerateWord32(0, 0xFFFF);
 | 
			
		||||
    u64_le local_friend_code_seed;
 | 
			
		||||
    rng.GenerateBlock(reinterpret_cast<byte*>(&local_friend_code_seed),
 | 
			
		||||
                      sizeof(local_friend_code_seed));
 | 
			
		||||
    console_id = (local_friend_code_seed & 0x3FFFFFFFF) | (static_cast<u64>(random_number) << 48);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) {
 | 
			
		||||
    u64_le console_id_le = console_id;
 | 
			
		||||
    ResultCode res =
 | 
			
		||||
        SetConfigInfoBlock(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    res = SetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    u32_le random_number_le = random_number;
 | 
			
		||||
    res = SetConfigInfoBlock(ConsoleUniqueID3BlockID, sizeof(random_number_le), 0xE,
 | 
			
		||||
                             &random_number_le);
 | 
			
		||||
    if (!res.IsSuccess())
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 GetConsoleUniqueId() {
 | 
			
		||||
    u64_le console_id_le;
 | 
			
		||||
    GetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le);
 | 
			
		||||
    return console_id_le;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace CFG
 | 
			
		||||
} // namespace Service
 | 
			
		||||
 
 | 
			
		||||
@@ -342,5 +342,26 @@ void SetSoundOutputMode(SoundOutputMode mode);
 | 
			
		||||
 */
 | 
			
		||||
SoundOutputMode GetSoundOutputMode();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generates a new random console unique id.
 | 
			
		||||
 * @param random_number a random generated 16bit number stored at 0x90002, used for generating the
 | 
			
		||||
 * console_id
 | 
			
		||||
 * @param console_id the randomly created console id
 | 
			
		||||
 */
 | 
			
		||||
void GenerateConsoleUniqueId(u32& random_number, u64& console_id);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sets the random_number and the  console unique id in the config savegame.
 | 
			
		||||
 * @param random_number the random_number to set
 | 
			
		||||
 * @param console_id the console id to set
 | 
			
		||||
 */
 | 
			
		||||
ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Gets the console unique id from config savegame.
 | 
			
		||||
 * @returns the console unique id
 | 
			
		||||
 */
 | 
			
		||||
u64 GetConsoleUniqueId();
 | 
			
		||||
 | 
			
		||||
} // namespace CFG
 | 
			
		||||
} // namespace Service
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user