From 281eb020ea6576e9525e35e4973313c39a553e8d Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 25 Nov 2023 22:19:46 -0600 Subject: [PATCH] service: nfc: Validate mii data --- .../hle/service/am/applets/applet_cabinet.cpp | 2 +- .../hle/service/mii/types/ver3_store_data.cpp | 2 +- src/core/hle/service/nfc/common/device.cpp | 70 ++++++++++--------- src/core/hle/service/nfc/common/device.h | 1 - 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index b379dadeb..a88d9d2ce 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -130,7 +130,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) nfp_device->DeleteApplicationArea(); break; case Service::NFP::CabinetMode::StartRestorer: - nfp_device->RestoreAmiibo(); + nfp_device->Restore(); break; case Service::NFP::CabinetMode::StartFormatter: nfp_device->Format(); diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp index a019cc9f7..c27646fcf 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.cpp +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp @@ -98,7 +98,7 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const { } void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { - version = 1; + version = 3; mii_information.gender.Assign(static_cast(store_data.GetGender())); mii_information.favorite_color.Assign(static_cast(store_data.GetFavoriteColor())); height = store_data.GetHeight(); diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index e7a00deb3..47516f883 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -401,6 +401,12 @@ Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& time } Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { + bool is_corrupted = false; + + if (model_type != NFP::ModelType::Amiibo) { + return ResultInvalidArgument; + } + if (device_state != DeviceState::TagFound) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); return ResultWrongDeviceState; @@ -420,26 +426,32 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target if (is_plain_amiibo) { std::vector data(sizeof(NFP::NTAG215File)); memcpy(data.data(), &tag_data, sizeof(tag_data)); - WriteBackupData(tag_data.uid, data); - - device_state = DeviceState::TagMounted; - mount_target = mount_target_; - return ResultSuccess; } - if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { - bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); - LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); - return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; + if (!is_plain_amiibo && !NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { + LOG_ERROR(Service_NFP, "Can't decode amiibo"); + is_corrupted = true; } - std::vector data(sizeof(NFP::EncryptedNTAG215File)); - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); - WriteBackupData(encrypted_tag_data.uuid, data); + if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { + LOG_ERROR(Service_NFP, "Invalid mii data"); + is_corrupted = true; + } + + if (!is_corrupted) { + std::vector data(sizeof(NFP::EncryptedNTAG215File)); + memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); + WriteBackupData(encrypted_tag_data.uuid, data); + } device_state = DeviceState::TagMounted; mount_target = mount_target_; + if (is_corrupted) { + bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); + return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; + } + return ResultSuccess; } @@ -606,6 +618,17 @@ Result NfcDevice::Restore() { } } + // Restore mii data in case is corrupted by previous instances of yuzu + if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { + LOG_ERROR(Service_NFP, "Regenerating mii data"); + Mii::StoreData new_mii{}; + new_mii.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All); + new_mii.SetNickname({u'y', u'u', u'z', u'u', u'\0'}); + + tag_data.owner_mii.BuildFromStoreData(new_mii); + tag_data.mii_extension.SetFromStoreData(new_mii); + } + // Overwrite tag contents with backup and mount the tag tag_data = temporary_tag_data; encrypted_tag_data = temporary_encrypted_tag_data; @@ -851,25 +874,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe return Flush(); } -Result NfcDevice::RestoreAmiibo() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return ResultTagRemoved; - } - return ResultWrongDeviceState; - } - - if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return ResultWrongDeviceState; - } - - // TODO: Load amiibo from backup on system - LOG_ERROR(Service_NFP, "Not Implemented"); - return ResultSuccess; -} - Result NfcDevice::Format() { Result result = ResultSuccess; @@ -877,7 +881,9 @@ Result NfcDevice::Format() { result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); } - if (result.IsError()) { + // We are formatting all data. Corruption is not an issue. + if (result.IsError() && + (result != ResultCorruptedData && result != ResultCorruptedDataWithBackup)) { return result; } diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 0ed1ff34c..d8efe25ec 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h @@ -68,7 +68,6 @@ public: Result DeleteRegisterInfo(); Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); - Result RestoreAmiibo(); Result Format(); Result OpenApplicationArea(u32 access_id);