service: nfc: Remove encryption key requirement

This commit is contained in:
Narr the Reg 2023-05-22 18:31:39 -06:00
parent f82efe9f65
commit f63586c5f5
3 changed files with 54 additions and 23 deletions

View File

@ -52,9 +52,6 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
if (ntag_file.compability_container != 0xEEFF10F1U) { if (ntag_file.compability_container != 0xEEFF10F1U) {
return false; return false;
} }
if (amiibo_data.constant_value != 0xA5) {
return false;
}
if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) { if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) {
return false; return false;
} }

View File

@ -119,18 +119,31 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data); is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data);
is_write_protected = false;
if (is_plain_amiibo) {
encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(tag_data);
LOG_INFO(Service_NFP, "Using plain amiibo");
} else {
tag_data = {};
memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
}
device_state = DeviceState::TagFound; device_state = DeviceState::TagFound;
deactivate_event->GetReadableEvent().Clear(); deactivate_event->GetReadableEvent().Clear();
activate_event->Signal(); activate_event->Signal();
// Fallback for plain amiibos
if (is_plain_amiibo) {
LOG_INFO(Service_NFP, "Using plain amiibo");
encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(tag_data);
return true;
}
// Fallback for encrypted amiibos without keys
if (!NFP::AmiiboCrypto::IsKeyAvailable()) {
LOG_INFO(Service_NFC, "Loading amiibo without keys");
memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
BuildAmiiboWithoutKeys();
is_plain_amiibo = true;
is_write_protected = true;
return true;
}
tag_data = {};
memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
return true; return true;
} }
@ -346,23 +359,15 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target
return ResultWrongDeviceState; return ResultWrongDeviceState;
} }
// The loaded amiibo is not encrypted
if (is_plain_amiibo) {
device_state = DeviceState::TagMounted;
mount_target = mount_target_;
return ResultSuccess;
}
if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
LOG_ERROR(Service_NFP, "Not an amiibo"); LOG_ERROR(Service_NFP, "Not an amiibo");
return ResultNotAnAmiibo; return ResultNotAnAmiibo;
} }
// Mark amiibos as read only when keys are missing // The loaded amiibo is not encrypted
if (!NFP::AmiiboCrypto::IsKeyAvailable()) { if (is_plain_amiibo) {
LOG_ERROR(Service_NFP, "No keys detected");
device_state = DeviceState::TagMounted; device_state = DeviceState::TagMounted;
mount_target = NFP::MountTarget::Rom; mount_target = mount_target_;
return ResultSuccess; return ResultSuccess;
} }
@ -457,6 +462,11 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) {
return ResultWrongDeviceState; return ResultWrongDeviceState;
} }
if (is_write_protected) {
LOG_ERROR(Service_NFP, "No keys available skipping write request");
return ResultSuccess;
}
std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File));
if (is_plain_amiibo) { if (is_plain_amiibo) {
memcpy(data.data(), &tag_data, sizeof(tag_data)); memcpy(data.data(), &tag_data, sizeof(tag_data));
@ -1033,7 +1043,6 @@ Result NfcDevice::GetAll(NFP::NfpData& data) const {
} }
NFP::CommonInfo common_info{}; NFP::CommonInfo common_info{};
Service::Mii::MiiManager manager;
const u64 application_id = tag_data.application_id; const u64 application_id = tag_data.application_id;
GetCommonInfo(common_info); GetCommonInfo(common_info);
@ -1249,6 +1258,28 @@ void NfcDevice::UpdateRegisterInfoCrc() {
tag_data.register_info_crc = crc.checksum(); tag_data.register_info_crc = crc.checksum();
} }
void NfcDevice::BuildAmiiboWithoutKeys() {
Service::Mii::MiiManager manager;
auto& settings = tag_data.settings;
tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_tag_data);
// Common info
tag_data.write_counter = 0;
tag_data.amiibo_version = 0;
settings.write_date = GetAmiiboDate(GetCurrentPosixTime());
// Register info
SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'});
settings.settings.font_region.Assign(0);
settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildDefault(0));
// Admin info
settings.settings.amiibo_initialized.Assign(1);
settings.settings.appdata_initialized.Assign(0);
}
u64 NfcDevice::GetHandle() const { u64 NfcDevice::GetHandle() const {
// Generate a handle based of the npad id // Generate a handle based of the npad id
return static_cast<u64>(npad_id); return static_cast<u64>(npad_id);

View File

@ -110,6 +110,8 @@ private:
void UpdateSettingsCrc(); void UpdateSettingsCrc();
void UpdateRegisterInfoCrc(); void UpdateRegisterInfoCrc();
void BuildAmiiboWithoutKeys();
bool is_controller_set{}; bool is_controller_set{};
int callback_key; int callback_key;
const Core::HID::NpadIdType npad_id; const Core::HID::NpadIdType npad_id;
@ -128,6 +130,7 @@ private:
bool is_data_moddified{}; bool is_data_moddified{};
bool is_app_area_open{}; bool is_app_area_open{};
bool is_plain_amiibo{}; bool is_plain_amiibo{};
bool is_write_protected{};
NFP::MountTarget mount_target{NFP::MountTarget::None}; NFP::MountTarget mount_target{NFP::MountTarget::None};
NFP::NTAG215File tag_data{}; NFP::NTAG215File tag_data{};