diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.cpp | 44 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.cpp | 164 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.h | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device_manager.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/mifare_result.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/nfc_interface.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/nfc_result.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/nfc_types.h | 37 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_types.h | 26 |
10 files changed, 198 insertions, 115 deletions
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp index b2bcb68c3..bc232c334 100644 --- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp +++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp | |||
| @@ -36,12 +36,12 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { | |||
| 36 | 36 | ||
| 37 | // Validate UUID | 37 | // Validate UUID |
| 38 | constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3` | 38 | constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3` |
| 39 | if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) != | 39 | if ((CT ^ ntag_file.uuid.part1[0] ^ ntag_file.uuid.part1[1] ^ ntag_file.uuid.part1[2]) != |
| 40 | ntag_file.uuid.uid[3]) { | 40 | ntag_file.uuid.crc_check1) { |
| 41 | return false; | 41 | return false; |
| 42 | } | 42 | } |
| 43 | if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^ | 43 | if ((ntag_file.uuid.part2[0] ^ ntag_file.uuid.part2[1] ^ ntag_file.uuid.part2[2] ^ |
| 44 | ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) { | 44 | ntag_file.uuid.nintendo_id) != ntag_file.uuid_crc_check2) { |
| 45 | return false; | 45 | return false; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| @@ -74,8 +74,9 @@ bool IsAmiiboValid(const NTAG215File& ntag_file) { | |||
| 74 | NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { | 74 | NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { |
| 75 | NTAG215File encoded_data{}; | 75 | NTAG215File encoded_data{}; |
| 76 | 76 | ||
| 77 | encoded_data.uid = nfc_data.uuid.uid; | 77 | encoded_data.uid = nfc_data.uuid; |
| 78 | encoded_data.nintendo_id = nfc_data.uuid.nintendo_id; | 78 | encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2; |
| 79 | encoded_data.internal_number = nfc_data.internal_number; | ||
| 79 | encoded_data.static_lock = nfc_data.static_lock; | 80 | encoded_data.static_lock = nfc_data.static_lock; |
| 80 | encoded_data.compability_container = nfc_data.compability_container; | 81 | encoded_data.compability_container = nfc_data.compability_container; |
| 81 | encoded_data.hmac_data = nfc_data.user_memory.hmac_data; | 82 | encoded_data.hmac_data = nfc_data.user_memory.hmac_data; |
| @@ -94,7 +95,6 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { | |||
| 94 | encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; | 95 | encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; |
| 95 | encoded_data.application_area = nfc_data.user_memory.application_area; | 96 | encoded_data.application_area = nfc_data.user_memory.application_area; |
| 96 | encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; | 97 | encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; |
| 97 | encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; | ||
| 98 | encoded_data.model_info = nfc_data.user_memory.model_info; | 98 | encoded_data.model_info = nfc_data.user_memory.model_info; |
| 99 | encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt; | 99 | encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt; |
| 100 | encoded_data.dynamic_lock = nfc_data.dynamic_lock; | 100 | encoded_data.dynamic_lock = nfc_data.dynamic_lock; |
| @@ -108,9 +108,9 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { | |||
| 108 | EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { | 108 | EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { |
| 109 | EncryptedNTAG215File nfc_data{}; | 109 | EncryptedNTAG215File nfc_data{}; |
| 110 | 110 | ||
| 111 | nfc_data.uuid.uid = encoded_data.uid; | 111 | nfc_data.uuid = encoded_data.uid; |
| 112 | nfc_data.uuid.nintendo_id = encoded_data.nintendo_id; | 112 | nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2; |
| 113 | nfc_data.uuid.lock_bytes = encoded_data.lock_bytes; | 113 | nfc_data.internal_number = encoded_data.internal_number; |
| 114 | nfc_data.static_lock = encoded_data.static_lock; | 114 | nfc_data.static_lock = encoded_data.static_lock; |
| 115 | nfc_data.compability_container = encoded_data.compability_container; | 115 | nfc_data.compability_container = encoded_data.compability_container; |
| 116 | nfc_data.user_memory.hmac_data = encoded_data.hmac_data; | 116 | nfc_data.user_memory.hmac_data = encoded_data.hmac_data; |
| @@ -139,23 +139,12 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { | |||
| 139 | return nfc_data; | 139 | return nfc_data; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | u32 GetTagPassword(const TagUuid& uuid) { | ||
| 143 | // Verify that the generated password is correct | ||
| 144 | u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]); | ||
| 145 | password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8; | ||
| 146 | password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16; | ||
| 147 | password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24; | ||
| 148 | return password; | ||
| 149 | } | ||
| 150 | |||
| 151 | HashSeed GetSeed(const NTAG215File& data) { | 142 | HashSeed GetSeed(const NTAG215File& data) { |
| 152 | HashSeed seed{ | 143 | HashSeed seed{ |
| 153 | .magic = data.write_counter, | 144 | .magic = data.write_counter, |
| 154 | .padding = {}, | 145 | .padding = {}, |
| 155 | .uid_1 = data.uid, | 146 | .uid_1 = data.uid, |
| 156 | .nintendo_id_1 = data.nintendo_id, | ||
| 157 | .uid_2 = data.uid, | 147 | .uid_2 = data.uid, |
| 158 | .nintendo_id_2 = data.nintendo_id, | ||
| 159 | .keygen_salt = data.keygen_salt, | 148 | .keygen_salt = data.keygen_salt, |
| 160 | }; | 149 | }; |
| 161 | 150 | ||
| @@ -177,10 +166,11 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed | |||
| 177 | output.insert(output.end(), key.magic_bytes.begin(), | 166 | output.insert(output.end(), key.magic_bytes.begin(), |
| 178 | key.magic_bytes.begin() + key.magic_length); | 167 | key.magic_bytes.begin() + key.magic_length); |
| 179 | 168 | ||
| 180 | output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end()); | 169 | std::array<u8, sizeof(NFP::TagUuid)> seed_uuid{}; |
| 181 | output.emplace_back(seed.nintendo_id_1); | 170 | memcpy(seed_uuid.data(), &seed.uid_1, sizeof(NFP::TagUuid)); |
| 182 | output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end()); | 171 | output.insert(output.end(), seed_uuid.begin(), seed_uuid.end()); |
| 183 | output.emplace_back(seed.nintendo_id_2); | 172 | memcpy(seed_uuid.data(), &seed.uid_2, sizeof(NFP::TagUuid)); |
| 173 | output.insert(output.end(), seed_uuid.begin(), seed_uuid.end()); | ||
| 184 | 174 | ||
| 185 | for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) { | 175 | for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) { |
| 186 | output.emplace_back(static_cast<u8>(seed.keygen_salt[i] ^ key.xor_pad[i])); | 176 | output.emplace_back(static_cast<u8>(seed.keygen_salt[i] ^ key.xor_pad[i])); |
| @@ -264,8 +254,8 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou | |||
| 264 | 254 | ||
| 265 | // Copy the rest of the data directly | 255 | // Copy the rest of the data directly |
| 266 | out_data.uid = in_data.uid; | 256 | out_data.uid = in_data.uid; |
| 267 | out_data.nintendo_id = in_data.nintendo_id; | 257 | out_data.uid_crc_check2 = in_data.uid_crc_check2; |
| 268 | out_data.lock_bytes = in_data.lock_bytes; | 258 | out_data.internal_number = in_data.internal_number; |
| 269 | out_data.static_lock = in_data.static_lock; | 259 | out_data.static_lock = in_data.static_lock; |
| 270 | out_data.compability_container = in_data.compability_container; | 260 | out_data.compability_container = in_data.compability_container; |
| 271 | 261 | ||
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h index bf3044ed9..6a3e0841e 100644 --- a/src/core/hle/service/nfc/common/amiibo_crypto.h +++ b/src/core/hle/service/nfc/common/amiibo_crypto.h | |||
| @@ -24,10 +24,8 @@ using DrgbOutput = std::array<u8, 0x20>; | |||
| 24 | struct HashSeed { | 24 | struct HashSeed { |
| 25 | u16_be magic; | 25 | u16_be magic; |
| 26 | std::array<u8, 0xE> padding; | 26 | std::array<u8, 0xE> padding; |
| 27 | NFC::UniqueSerialNumber uid_1; | 27 | TagUuid uid_1; |
| 28 | u8 nintendo_id_1; | 28 | TagUuid uid_2; |
| 29 | NFC::UniqueSerialNumber uid_2; | ||
| 30 | u8 nintendo_id_2; | ||
| 31 | std::array<u8, 0x20> keygen_salt; | 29 | std::array<u8, 0x20> keygen_salt; |
| 32 | }; | 30 | }; |
| 33 | static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size"); | 31 | static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size"); |
| @@ -69,9 +67,6 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data); | |||
| 69 | /// Converts from encoded file format to encrypted file format | 67 | /// Converts from encoded file format to encrypted file format |
| 70 | EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data); | 68 | EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data); |
| 71 | 69 | ||
| 72 | /// Returns password needed to allow write access to protected memory | ||
| 73 | u32 GetTagPassword(const TagUuid& uuid); | ||
| 74 | |||
| 75 | // Generates Seed needed for key derivation | 70 | // Generates Seed needed for key derivation |
| 76 | HashSeed GetSeed(const NTAG215File& data); | 71 | HashSeed GetSeed(const NTAG215File& data); |
| 77 | 72 | ||
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index b14f682b5..f4b180b06 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -242,34 +242,39 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { | |||
| 242 | return ResultWrongDeviceState; | 242 | return ResultWrongDeviceState; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | UniqueSerialNumber uuid = encrypted_tag_data.uuid.uid; | 245 | UniqueSerialNumber uuid{}; |
| 246 | 246 | u8 uuid_length{}; | |
| 247 | // Generate random UUID to bypass amiibo load limits | 247 | NfcProtocol protocol{NfcProtocol::TypeA}; |
| 248 | if (Settings::values.random_amiibo_id) { | 248 | TagType tag_type{TagType::Type2}; |
| 249 | Common::TinyMT rng{}; | ||
| 250 | rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); | ||
| 251 | rng.GenerateRandomBytes(uuid.data(), sizeof(UniqueSerialNumber)); | ||
| 252 | uuid[3] = 0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2]; | ||
| 253 | } | ||
| 254 | 249 | ||
| 255 | if (is_mifare) { | 250 | if (is_mifare) { |
| 256 | tag_info = { | 251 | tag_type = TagType::Mifare; |
| 257 | .uuid = uuid, | 252 | uuid_length = sizeof(NFP::NtagTagUuid); |
| 258 | .uuid_extension = {}, | 253 | memcpy(uuid.data(), mifare_data.data(), uuid_length); |
| 259 | .uuid_length = static_cast<u8>(uuid.size()), | 254 | } else { |
| 260 | .protocol = NfcProtocol::TypeA, | 255 | tag_type = TagType::Type2; |
| 261 | .tag_type = TagType::Type4, | 256 | uuid_length = sizeof(NFP::NtagTagUuid); |
| 257 | NFP::NtagTagUuid nUuid{ | ||
| 258 | .part1 = encrypted_tag_data.uuid.part1, | ||
| 259 | .part2 = encrypted_tag_data.uuid.part2, | ||
| 260 | .nintendo_id = encrypted_tag_data.uuid.nintendo_id, | ||
| 262 | }; | 261 | }; |
| 263 | return ResultSuccess; | 262 | memcpy(uuid.data(), &nUuid, uuid_length); |
| 263 | |||
| 264 | // Generate random UUID to bypass amiibo load limits | ||
| 265 | if (Settings::values.random_amiibo_id) { | ||
| 266 | Common::TinyMT rng{}; | ||
| 267 | rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); | ||
| 268 | rng.GenerateRandomBytes(uuid.data(), uuid_length); | ||
| 269 | } | ||
| 264 | } | 270 | } |
| 265 | 271 | ||
| 266 | // Protocol and tag type may change here | 272 | // Protocol and tag type may change here |
| 267 | tag_info = { | 273 | tag_info = { |
| 268 | .uuid = uuid, | 274 | .uuid = uuid, |
| 269 | .uuid_extension = {}, | 275 | .uuid_length = uuid_length, |
| 270 | .uuid_length = static_cast<u8>(uuid.size()), | 276 | .protocol = protocol, |
| 271 | .protocol = NfcProtocol::TypeA, | 277 | .tag_type = tag_type, |
| 272 | .tag_type = TagType::Type2, | ||
| 273 | }; | 278 | }; |
| 274 | 279 | ||
| 275 | return ResultSuccess; | 280 | return ResultSuccess; |
| @@ -277,8 +282,38 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { | |||
| 277 | 282 | ||
| 278 | Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters, | 283 | Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters, |
| 279 | std::span<MifareReadBlockData> read_block_data) const { | 284 | std::span<MifareReadBlockData> read_block_data) const { |
| 285 | if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { | ||
| 286 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | ||
| 287 | if (device_state == DeviceState::TagRemoved) { | ||
| 288 | return ResultTagRemoved; | ||
| 289 | } | ||
| 290 | return ResultWrongDeviceState; | ||
| 291 | } | ||
| 292 | |||
| 280 | Result result = ResultSuccess; | 293 | Result result = ResultSuccess; |
| 281 | 294 | ||
| 295 | TagInfo tag_info{}; | ||
| 296 | result = GetTagInfo(tag_info, true); | ||
| 297 | |||
| 298 | if (result.IsError()) { | ||
| 299 | return result; | ||
| 300 | } | ||
| 301 | |||
| 302 | if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) { | ||
| 303 | return ResultInvalidTagType; | ||
| 304 | } | ||
| 305 | |||
| 306 | if (parameters.size() == 0) { | ||
| 307 | return ResultInvalidArgument; | ||
| 308 | } | ||
| 309 | |||
| 310 | const auto unknown = parameters[0].sector_key.unknown; | ||
| 311 | for (std::size_t i = 0; i < parameters.size(); i++) { | ||
| 312 | if (unknown != parameters[i].sector_key.unknown) { | ||
| 313 | return ResultInvalidArgument; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 282 | for (std::size_t i = 0; i < parameters.size(); i++) { | 317 | for (std::size_t i = 0; i < parameters.size(); i++) { |
| 283 | result = ReadMifare(parameters[i], read_block_data[i]); | 318 | result = ReadMifare(parameters[i], read_block_data[i]); |
| 284 | if (result.IsError()) { | 319 | if (result.IsError()) { |
| @@ -293,17 +328,8 @@ Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter, | |||
| 293 | MifareReadBlockData& read_block_data) const { | 328 | MifareReadBlockData& read_block_data) const { |
| 294 | const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); | 329 | const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); |
| 295 | read_block_data.sector_number = parameter.sector_number; | 330 | read_block_data.sector_number = parameter.sector_number; |
| 296 | |||
| 297 | if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { | ||
| 298 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | ||
| 299 | if (device_state == DeviceState::TagRemoved) { | ||
| 300 | return ResultTagRemoved; | ||
| 301 | } | ||
| 302 | return ResultWrongDeviceState; | ||
| 303 | } | ||
| 304 | |||
| 305 | if (mifare_data.size() < sector_index + sizeof(DataBlock)) { | 331 | if (mifare_data.size() < sector_index + sizeof(DataBlock)) { |
| 306 | return Mifare::ResultReadError; | 332 | return ResultMifareError288; |
| 307 | } | 333 | } |
| 308 | 334 | ||
| 309 | // TODO: Use parameter.sector_key to read encrypted data | 335 | // TODO: Use parameter.sector_key to read encrypted data |
| @@ -315,6 +341,28 @@ Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter, | |||
| 315 | Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) { | 341 | Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) { |
| 316 | Result result = ResultSuccess; | 342 | Result result = ResultSuccess; |
| 317 | 343 | ||
| 344 | TagInfo tag_info{}; | ||
| 345 | result = GetTagInfo(tag_info, true); | ||
| 346 | |||
| 347 | if (result.IsError()) { | ||
| 348 | return result; | ||
| 349 | } | ||
| 350 | |||
| 351 | if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) { | ||
| 352 | return ResultInvalidTagType; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (parameters.size() == 0) { | ||
| 356 | return ResultInvalidArgument; | ||
| 357 | } | ||
| 358 | |||
| 359 | const auto unknown = parameters[0].sector_key.unknown; | ||
| 360 | for (std::size_t i = 0; i < parameters.size(); i++) { | ||
| 361 | if (unknown != parameters[i].sector_key.unknown) { | ||
| 362 | return ResultInvalidArgument; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 318 | for (std::size_t i = 0; i < parameters.size(); i++) { | 366 | for (std::size_t i = 0; i < parameters.size(); i++) { |
| 319 | result = WriteMifare(parameters[i]); | 367 | result = WriteMifare(parameters[i]); |
| 320 | if (result.IsError()) { | 368 | if (result.IsError()) { |
| @@ -324,7 +372,7 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet | |||
| 324 | 372 | ||
| 325 | if (!npad_device->WriteNfc(mifare_data)) { | 373 | if (!npad_device->WriteNfc(mifare_data)) { |
| 326 | LOG_ERROR(Service_NFP, "Error writing to file"); | 374 | LOG_ERROR(Service_NFP, "Error writing to file"); |
| 327 | return Mifare::ResultReadError; | 375 | return ResultMifareError288; |
| 328 | } | 376 | } |
| 329 | 377 | ||
| 330 | return result; | 378 | return result; |
| @@ -342,7 +390,7 @@ Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) { | |||
| 342 | } | 390 | } |
| 343 | 391 | ||
| 344 | if (mifare_data.size() < sector_index + sizeof(DataBlock)) { | 392 | if (mifare_data.size() < sector_index + sizeof(DataBlock)) { |
| 345 | return Mifare::ResultReadError; | 393 | return ResultMifareError288; |
| 346 | } | 394 | } |
| 347 | 395 | ||
| 348 | // TODO: Use parameter.sector_key to encrypt the data | 396 | // TODO: Use parameter.sector_key to encrypt the data |
| @@ -366,7 +414,7 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target | |||
| 366 | 414 | ||
| 367 | if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { | 415 | if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { |
| 368 | LOG_ERROR(Service_NFP, "Not an amiibo"); | 416 | LOG_ERROR(Service_NFP, "Not an amiibo"); |
| 369 | return ResultNotAnAmiibo; | 417 | return ResultInvalidTagType; |
| 370 | } | 418 | } |
| 371 | 419 | ||
| 372 | // The loaded amiibo is not encrypted | 420 | // The loaded amiibo is not encrypted |
| @@ -381,14 +429,14 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target | |||
| 381 | } | 429 | } |
| 382 | 430 | ||
| 383 | if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { | 431 | if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { |
| 384 | bool has_backup = HasBackup(encrypted_tag_data.uuid.uid).IsSuccess(); | 432 | bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); |
| 385 | LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); | 433 | LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); |
| 386 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; | 434 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; |
| 387 | } | 435 | } |
| 388 | 436 | ||
| 389 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); | 437 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); |
| 390 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | 438 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); |
| 391 | WriteBackupData(encrypted_tag_data.uuid.uid, data); | 439 | WriteBackupData(encrypted_tag_data.uuid, data); |
| 392 | 440 | ||
| 393 | device_state = DeviceState::TagMounted; | 441 | device_state = DeviceState::TagMounted; |
| 394 | mount_target = mount_target_; | 442 | mount_target = mount_target_; |
| @@ -492,7 +540,7 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) { | |||
| 492 | } | 540 | } |
| 493 | 541 | ||
| 494 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | 542 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); |
| 495 | WriteBackupData(encrypted_tag_data.uuid.uid, data); | 543 | WriteBackupData(encrypted_tag_data.uuid, data); |
| 496 | } | 544 | } |
| 497 | 545 | ||
| 498 | if (!npad_device->WriteNfc(data)) { | 546 | if (!npad_device->WriteNfc(data)) { |
| @@ -520,7 +568,7 @@ Result NfcDevice::Restore() { | |||
| 520 | return result; | 568 | return result; |
| 521 | } | 569 | } |
| 522 | 570 | ||
| 523 | result = ReadBackupData(tag_info.uuid, data); | 571 | result = ReadBackupData(tag_info.uuid, tag_info.uuid_length, data); |
| 524 | 572 | ||
| 525 | if (result.IsError()) { | 573 | if (result.IsError()) { |
| 526 | return result; | 574 | return result; |
| @@ -548,7 +596,7 @@ Result NfcDevice::Restore() { | |||
| 548 | } | 596 | } |
| 549 | 597 | ||
| 550 | if (!NFP::AmiiboCrypto::IsAmiiboValid(temporary_encrypted_tag_data)) { | 598 | if (!NFP::AmiiboCrypto::IsAmiiboValid(temporary_encrypted_tag_data)) { |
| 551 | return ResultNotAnAmiibo; | 599 | return ResultInvalidTagType; |
| 552 | } | 600 | } |
| 553 | 601 | ||
| 554 | if (!is_plain_amiibo) { | 602 | if (!is_plain_amiibo) { |
| @@ -1194,10 +1242,12 @@ Result NfcDevice::BreakTag(NFP::BreakType break_type) { | |||
| 1194 | return FlushWithBreak(break_type); | 1242 | return FlushWithBreak(break_type); |
| 1195 | } | 1243 | } |
| 1196 | 1244 | ||
| 1197 | Result NfcDevice::HasBackup(const NFC::UniqueSerialNumber& uid) const { | 1245 | Result NfcDevice::HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const { |
| 1246 | ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); | ||
| 1198 | constexpr auto backup_dir = "backup"; | 1247 | constexpr auto backup_dir = "backup"; |
| 1199 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | 1248 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); |
| 1200 | const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | 1249 | const auto file_name = |
| 1250 | fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); | ||
| 1201 | 1251 | ||
| 1202 | if (!Common::FS::Exists(yuzu_amiibo_dir / backup_dir / file_name)) { | 1252 | if (!Common::FS::Exists(yuzu_amiibo_dir / backup_dir / file_name)) { |
| 1203 | return ResultUnableToAccessBackupFile; | 1253 | return ResultUnableToAccessBackupFile; |
| @@ -1206,10 +1256,19 @@ Result NfcDevice::HasBackup(const NFC::UniqueSerialNumber& uid) const { | |||
| 1206 | return ResultSuccess; | 1256 | return ResultSuccess; |
| 1207 | } | 1257 | } |
| 1208 | 1258 | ||
| 1209 | Result NfcDevice::ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const { | 1259 | Result NfcDevice::HasBackup(const NFP::TagUuid& tag_uid) const { |
| 1260 | UniqueSerialNumber uuid{}; | ||
| 1261 | memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); | ||
| 1262 | return HasBackup(uuid, sizeof(NFP::TagUuid)); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | Result NfcDevice::ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, | ||
| 1266 | std::span<u8> data) const { | ||
| 1267 | ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); | ||
| 1210 | constexpr auto backup_dir = "backup"; | 1268 | constexpr auto backup_dir = "backup"; |
| 1211 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | 1269 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); |
| 1212 | const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | 1270 | const auto file_name = |
| 1271 | fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); | ||
| 1213 | 1272 | ||
| 1214 | const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, | 1273 | const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, |
| 1215 | Common::FS::FileAccessMode::Read, | 1274 | Common::FS::FileAccessMode::Read, |
| @@ -1228,12 +1287,21 @@ Result NfcDevice::ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u | |||
| 1228 | return ResultSuccess; | 1287 | return ResultSuccess; |
| 1229 | } | 1288 | } |
| 1230 | 1289 | ||
| 1231 | Result NfcDevice::WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data) { | 1290 | Result NfcDevice::ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const { |
| 1291 | UniqueSerialNumber uuid{}; | ||
| 1292 | memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); | ||
| 1293 | return ReadBackupData(uuid, sizeof(NFP::TagUuid), data); | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | Result NfcDevice::WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, | ||
| 1297 | std::span<const u8> data) { | ||
| 1298 | ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size"); | ||
| 1232 | constexpr auto backup_dir = "backup"; | 1299 | constexpr auto backup_dir = "backup"; |
| 1233 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | 1300 | const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); |
| 1234 | const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | 1301 | const auto file_name = |
| 1302 | fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, "")); | ||
| 1235 | 1303 | ||
| 1236 | if (HasBackup(uid).IsError()) { | 1304 | if (HasBackup(uid, uuid_size).IsError()) { |
| 1237 | if (!Common::FS::CreateDir(yuzu_amiibo_dir / backup_dir)) { | 1305 | if (!Common::FS::CreateDir(yuzu_amiibo_dir / backup_dir)) { |
| 1238 | return ResultBackupPathAlreadyExist; | 1306 | return ResultBackupPathAlreadyExist; |
| 1239 | } | 1307 | } |
| @@ -1260,6 +1328,12 @@ Result NfcDevice::WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span< | |||
| 1260 | return ResultSuccess; | 1328 | return ResultSuccess; |
| 1261 | } | 1329 | } |
| 1262 | 1330 | ||
| 1331 | Result NfcDevice::WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data) { | ||
| 1332 | UniqueSerialNumber uuid{}; | ||
| 1333 | memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid)); | ||
| 1334 | return WriteBackupData(uuid, sizeof(NFP::TagUuid), data); | ||
| 1335 | } | ||
| 1336 | |||
| 1263 | Result NfcDevice::WriteNtf(std::span<const u8> data) { | 1337 | Result NfcDevice::WriteNtf(std::span<const u8> data) { |
| 1264 | if (device_state != DeviceState::TagMounted) { | 1338 | if (device_state != DeviceState::TagMounted) { |
| 1265 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | 1339 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); |
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 6f049b687..7560210d6 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h | |||
| @@ -86,9 +86,14 @@ public: | |||
| 86 | Result GetAll(NFP::NfpData& data) const; | 86 | Result GetAll(NFP::NfpData& data) const; |
| 87 | Result SetAll(const NFP::NfpData& data); | 87 | Result SetAll(const NFP::NfpData& data); |
| 88 | Result BreakTag(NFP::BreakType break_type); | 88 | Result BreakTag(NFP::BreakType break_type); |
| 89 | Result HasBackup(const NFC::UniqueSerialNumber& uid) const; | 89 | Result HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const; |
| 90 | Result ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const; | 90 | Result HasBackup(const NFP::TagUuid& tag_uid) const; |
| 91 | Result WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data); | 91 | Result ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, |
| 92 | std::span<u8> data) const; | ||
| 93 | Result ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const; | ||
| 94 | Result WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size, | ||
| 95 | std::span<const u8> data); | ||
| 96 | Result WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data); | ||
| 92 | Result WriteNtf(std::span<const u8> data); | 97 | Result WriteNtf(std::span<const u8> data); |
| 93 | 98 | ||
| 94 | u64 GetHandle() const; | 99 | u64 GetHandle() const; |
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index cffd602df..b0456508e 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp | |||
| @@ -550,7 +550,7 @@ Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) cons | |||
| 550 | } | 550 | } |
| 551 | 551 | ||
| 552 | if (result.IsSuccess()) { | 552 | if (result.IsSuccess()) { |
| 553 | result = device->ReadBackupData(tag_info.uuid, data); | 553 | result = device->ReadBackupData(tag_info.uuid, tag_info.uuid_length, data); |
| 554 | result = VerifyDeviceResult(device, result); | 554 | result = VerifyDeviceResult(device, result); |
| 555 | } | 555 | } |
| 556 | 556 | ||
| @@ -569,7 +569,7 @@ Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> dat | |||
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | if (result.IsSuccess()) { | 571 | if (result.IsSuccess()) { |
| 572 | result = device->WriteBackupData(tag_info.uuid, data); | 572 | result = device->WriteBackupData(tag_info.uuid, tag_info.uuid_length, data); |
| 573 | result = VerifyDeviceResult(device, result); | 573 | result = VerifyDeviceResult(device, result); |
| 574 | } | 574 | } |
| 575 | 575 | ||
diff --git a/src/core/hle/service/nfc/mifare_result.h b/src/core/hle/service/nfc/mifare_result.h index 4b60048a5..16a9171e6 100644 --- a/src/core/hle/service/nfc/mifare_result.h +++ b/src/core/hle/service/nfc/mifare_result.h | |||
| @@ -12,6 +12,6 @@ constexpr Result ResultInvalidArgument(ErrorModule::NFCMifare, 65); | |||
| 12 | constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73); | 12 | constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73); |
| 13 | constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80); | 13 | constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80); |
| 14 | constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97); | 14 | constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97); |
| 15 | constexpr Result ResultReadError(ErrorModule::NFCMifare, 288); | 15 | constexpr Result ResultNotAMifare(ErrorModule::NFCMifare, 288); |
| 16 | 16 | ||
| 17 | } // namespace Service::NFC::Mifare | 17 | } // namespace Service::NFC::Mifare |
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 198d0f2b9..130fb7f78 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp | |||
| @@ -142,9 +142,13 @@ void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { | |||
| 142 | void NfcInterface::StartDetection(HLERequestContext& ctx) { | 142 | void NfcInterface::StartDetection(HLERequestContext& ctx) { |
| 143 | IPC::RequestParser rp{ctx}; | 143 | IPC::RequestParser rp{ctx}; |
| 144 | const auto device_handle{rp.Pop<u64>()}; | 144 | const auto device_handle{rp.Pop<u64>()}; |
| 145 | const auto tag_protocol{rp.PopEnum<NfcProtocol>()}; | 145 | auto tag_protocol{NfcProtocol::All}; |
| 146 | LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol); | 146 | |
| 147 | if (backend_type == BackendType::Nfc) { | ||
| 148 | tag_protocol = rp.PopEnum<NfcProtocol>(); | ||
| 149 | } | ||
| 147 | 150 | ||
| 151 | LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol); | ||
| 148 | auto result = GetManager()->StartDetection(device_handle, tag_protocol); | 152 | auto result = GetManager()->StartDetection(device_handle, tag_protocol); |
| 149 | result = TranslateResultToServiceError(result); | 153 | result = TranslateResultToServiceError(result); |
| 150 | 154 | ||
| @@ -355,7 +359,7 @@ Result NfcInterface::TranslateResultToNfp(Result result) const { | |||
| 355 | if (result == ResultApplicationAreaExist) { | 359 | if (result == ResultApplicationAreaExist) { |
| 356 | return NFP::ResultApplicationAreaExist; | 360 | return NFP::ResultApplicationAreaExist; |
| 357 | } | 361 | } |
| 358 | if (result == ResultNotAnAmiibo) { | 362 | if (result == ResultInvalidTagType) { |
| 359 | return NFP::ResultNotAnAmiibo; | 363 | return NFP::ResultNotAnAmiibo; |
| 360 | } | 364 | } |
| 361 | if (result == ResultUnableToAccessBackupFile) { | 365 | if (result == ResultUnableToAccessBackupFile) { |
| @@ -381,6 +385,9 @@ Result NfcInterface::TranslateResultToMifare(Result result) const { | |||
| 381 | if (result == ResultTagRemoved) { | 385 | if (result == ResultTagRemoved) { |
| 382 | return Mifare::ResultTagRemoved; | 386 | return Mifare::ResultTagRemoved; |
| 383 | } | 387 | } |
| 388 | if (result == ResultInvalidTagType) { | ||
| 389 | return Mifare::ResultNotAMifare; | ||
| 390 | } | ||
| 384 | LOG_WARNING(Service_NFC, "Result conversion not handled"); | 391 | LOG_WARNING(Service_NFC, "Result conversion not handled"); |
| 385 | return result; | 392 | return result; |
| 386 | } | 393 | } |
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h index 59a808740..715c0e80c 100644 --- a/src/core/hle/service/nfc/nfc_result.h +++ b/src/core/hle/service/nfc/nfc_result.h | |||
| @@ -24,7 +24,8 @@ constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136); | |||
| 24 | constexpr Result ResultCorruptedData(ErrorModule::NFC, 144); | 24 | constexpr Result ResultCorruptedData(ErrorModule::NFC, 144); |
| 25 | constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFC, 152); | 25 | constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFC, 152); |
| 26 | constexpr Result ResultApplicationAreaExist(ErrorModule::NFC, 168); | 26 | constexpr Result ResultApplicationAreaExist(ErrorModule::NFC, 168); |
| 27 | constexpr Result ResultNotAnAmiibo(ErrorModule::NFC, 178); | 27 | constexpr Result ResultInvalidTagType(ErrorModule::NFC, 178); |
| 28 | constexpr Result ResultBackupPathAlreadyExist(ErrorModule::NFC, 216); | 28 | constexpr Result ResultBackupPathAlreadyExist(ErrorModule::NFC, 216); |
| 29 | constexpr Result ResultMifareError288(ErrorModule::NFC, 288); | ||
| 29 | 30 | ||
| 30 | } // namespace Service::NFC | 31 | } // namespace Service::NFC |
diff --git a/src/core/hle/service/nfc/nfc_types.h b/src/core/hle/service/nfc/nfc_types.h index c7ebd1fdb..68e724442 100644 --- a/src/core/hle/service/nfc/nfc_types.h +++ b/src/core/hle/service/nfc/nfc_types.h | |||
| @@ -35,32 +35,35 @@ enum class State : u32 { | |||
| 35 | 35 | ||
| 36 | // This is nn::nfc::TagType | 36 | // This is nn::nfc::TagType |
| 37 | enum class TagType : u32 { | 37 | enum class TagType : u32 { |
| 38 | None, | 38 | None = 0, |
| 39 | Type1, // ISO14443A RW 96-2k bytes 106kbit/s | 39 | Type1 = 1U << 0, // ISO14443A RW. Topaz |
| 40 | Type2, // ISO14443A RW/RO 540 bytes 106kbit/s | 40 | Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN |
| 41 | Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s | 41 | Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa |
| 42 | Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s | 42 | Type4A = 1U << 3, // ISO14443A RW/RO. DESFire |
| 43 | Type5, // ISO15693 RW/RO 540 bytes 106kbit/s | 43 | Type4B = 1U << 4, // ISO14443B RW/RO. DESFire |
| 44 | Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV | ||
| 45 | Mifare = 1U << 6, // Mifare classic. Skylanders | ||
| 46 | All = 0xFFFFFFFF, | ||
| 44 | }; | 47 | }; |
| 45 | 48 | ||
| 46 | enum class PackedTagType : u8 { | 49 | enum class PackedTagType : u8 { |
| 47 | None, | 50 | None = 0, |
| 48 | Type1, // ISO14443A RW 96-2k bytes 106kbit/s | 51 | Type1 = 1U << 0, // ISO14443A RW. Topaz |
| 49 | Type2, // ISO14443A RW/RO 540 bytes 106kbit/s | 52 | Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN |
| 50 | Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s | 53 | Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa |
| 51 | Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s | 54 | Type4A = 1U << 3, // ISO14443A RW/RO. DESFire |
| 52 | Type5, // ISO15693 RW/RO 540 bytes 106kbit/s | 55 | Type4B = 1U << 4, // ISO14443B RW/RO. DESFire |
| 56 | Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV | ||
| 57 | Mifare = 1U << 6, // Mifare classic. Skylanders | ||
| 58 | All = 0xFF, | ||
| 53 | }; | 59 | }; |
| 54 | 60 | ||
| 55 | // This is nn::nfc::NfcProtocol | 61 | // This is nn::nfc::NfcProtocol |
| 56 | // Verify this enum. It might be completely wrong default protocol is 0x48 | ||
| 57 | enum class NfcProtocol : u32 { | 62 | enum class NfcProtocol : u32 { |
| 58 | None, | 63 | None, |
| 59 | TypeA = 1U << 0, // ISO14443A | 64 | TypeA = 1U << 0, // ISO14443A |
| 60 | TypeB = 1U << 1, // ISO14443B | 65 | TypeB = 1U << 1, // ISO14443B |
| 61 | TypeF = 1U << 2, // Sony FeliCa | 66 | TypeF = 1U << 2, // Sony FeliCa |
| 62 | Unknown1 = 1U << 3, | ||
| 63 | Unknown2 = 1U << 5, | ||
| 64 | All = 0xFFFFFFFFU, | 67 | All = 0xFFFFFFFFU, |
| 65 | }; | 68 | }; |
| 66 | 69 | ||
| @@ -69,8 +72,7 @@ enum class TestWaveType : u32 { | |||
| 69 | Unknown, | 72 | Unknown, |
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| 72 | using UniqueSerialNumber = std::array<u8, 7>; | 75 | using UniqueSerialNumber = std::array<u8, 10>; |
| 73 | using UniqueSerialNumberExtension = std::array<u8, 3>; | ||
| 74 | 76 | ||
| 75 | // This is nn::nfc::DeviceHandle | 77 | // This is nn::nfc::DeviceHandle |
| 76 | using DeviceHandle = u64; | 78 | using DeviceHandle = u64; |
| @@ -78,7 +80,6 @@ using DeviceHandle = u64; | |||
| 78 | // This is nn::nfc::TagInfo | 80 | // This is nn::nfc::TagInfo |
| 79 | struct TagInfo { | 81 | struct TagInfo { |
| 80 | UniqueSerialNumber uuid; | 82 | UniqueSerialNumber uuid; |
| 81 | UniqueSerialNumberExtension uuid_extension; | ||
| 82 | u8 uuid_length; | 83 | u8 uuid_length; |
| 83 | INSERT_PADDING_BYTES(0x15); | 84 | INSERT_PADDING_BYTES(0x15); |
| 84 | NfcProtocol protocol; | 85 | NfcProtocol protocol; |
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 7d36d5ee6..aed12a7f8 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h | |||
| @@ -85,7 +85,7 @@ enum class CabinetMode : u8 { | |||
| 85 | StartFormatter, | 85 | StartFormatter, |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | using LockBytes = std::array<u8, 2>; | 88 | using UuidPart = std::array<u8, 3>; |
| 89 | using HashData = std::array<u8, 0x20>; | 89 | using HashData = std::array<u8, 0x20>; |
| 90 | using ApplicationArea = std::array<u8, 0xD8>; | 90 | using ApplicationArea = std::array<u8, 0xD8>; |
| 91 | using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; | 91 | using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; |
| @@ -93,12 +93,20 @@ using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; | |||
| 93 | // This is nn::nfp::TagInfo | 93 | // This is nn::nfp::TagInfo |
| 94 | using TagInfo = NFC::TagInfo; | 94 | using TagInfo = NFC::TagInfo; |
| 95 | 95 | ||
| 96 | struct NtagTagUuid { | ||
| 97 | UuidPart part1; | ||
| 98 | UuidPart part2; | ||
| 99 | u8 nintendo_id; | ||
| 100 | }; | ||
| 101 | static_assert(sizeof(NtagTagUuid) == 7, "NtagTagUuid is an invalid size"); | ||
| 102 | |||
| 96 | struct TagUuid { | 103 | struct TagUuid { |
| 97 | NFC::UniqueSerialNumber uid; | 104 | UuidPart part1; |
| 105 | u8 crc_check1; | ||
| 106 | UuidPart part2; | ||
| 98 | u8 nintendo_id; | 107 | u8 nintendo_id; |
| 99 | LockBytes lock_bytes; | ||
| 100 | }; | 108 | }; |
| 101 | static_assert(sizeof(TagUuid) == 10, "TagUuid is an invalid size"); | 109 | static_assert(sizeof(TagUuid) == 8, "TagUuid is an invalid size"); |
| 102 | 110 | ||
| 103 | struct WriteDate { | 111 | struct WriteDate { |
| 104 | u16 year; | 112 | u16 year; |
| @@ -231,7 +239,8 @@ struct EncryptedAmiiboFile { | |||
| 231 | static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); | 239 | static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); |
| 232 | 240 | ||
| 233 | struct NTAG215File { | 241 | struct NTAG215File { |
| 234 | LockBytes lock_bytes; // Tag UUID | 242 | u8 uid_crc_check2; |
| 243 | u8 internal_number; | ||
| 235 | u16 static_lock; // Set defined pages as read only | 244 | u16 static_lock; // Set defined pages as read only |
| 236 | u32 compability_container; // Defines available memory | 245 | u32 compability_container; // Defines available memory |
| 237 | HashData hmac_data; // Hash | 246 | HashData hmac_data; // Hash |
| @@ -250,8 +259,7 @@ struct NTAG215File { | |||
| 250 | u32_be register_info_crc; | 259 | u32_be register_info_crc; |
| 251 | ApplicationArea application_area; // Encrypted Game data | 260 | ApplicationArea application_area; // Encrypted Game data |
| 252 | HashData hmac_tag; // Hash | 261 | HashData hmac_tag; // Hash |
| 253 | NFC::UniqueSerialNumber uid; // Unique serial number | 262 | TagUuid uid; |
| 254 | u8 nintendo_id; // Tag UUID | ||
| 255 | AmiiboModelInfo model_info; | 263 | AmiiboModelInfo model_info; |
| 256 | HashData keygen_salt; // Salt | 264 | HashData keygen_salt; // Salt |
| 257 | u32 dynamic_lock; // Dynamic lock | 265 | u32 dynamic_lock; // Dynamic lock |
| @@ -264,7 +272,9 @@ static_assert(std::is_trivially_copyable_v<NTAG215File>, "NTAG215File must be tr | |||
| 264 | #pragma pack() | 272 | #pragma pack() |
| 265 | 273 | ||
| 266 | struct EncryptedNTAG215File { | 274 | struct EncryptedNTAG215File { |
| 267 | TagUuid uuid; // Unique serial number | 275 | TagUuid uuid; |
| 276 | u8 uuid_crc_check2; | ||
| 277 | u8 internal_number; | ||
| 268 | u16 static_lock; // Set defined pages as read only | 278 | u16 static_lock; // Set defined pages as read only |
| 269 | u32 compability_container; // Defines available memory | 279 | u32 compability_container; // Defines available memory |
| 270 | EncryptedAmiiboFile user_memory; // Writable data | 280 | EncryptedAmiiboFile user_memory; // Writable data |