summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar german772022-09-26 00:58:36 -0500
committerGravatar german772022-10-02 12:32:26 -0500
commit673de3995b7f08d51fcc281439c05c368b7bd1ae (patch)
treeb1af8c6bd552c902929c8367a09d20fd33beb962
parentservice: nfp: address comments (diff)
downloadyuzu-673de3995b7f08d51fcc281439c05c368b7bd1ae.tar.gz
yuzu-673de3995b7f08d51fcc281439c05c368b7bd1ae.tar.xz
yuzu-673de3995b7f08d51fcc281439c05c368b7bd1ae.zip
nfp: Multiple fixes against HW
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp68
-rw-r--r--src/core/hle/service/mii/mii_manager.h1
-rw-r--r--src/core/hle/service/nfc/nfc.cpp8
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.cpp55
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.h6
-rw-r--r--src/core/hle/service/nfp/nfp_device.cpp60
-rw-r--r--src/core/hle/service/nfp/nfp_device.h2
-rw-r--r--src/core/hle/service/nfp/nfp_result.h1
-rw-r--r--src/core/hle/service/nfp/nfp_types.h24
9 files changed, 163 insertions, 62 deletions
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 3e92152ec..4bc8703e1 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -431,8 +431,7 @@ CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
431 Service::Mii::MiiManager manager; 431 Service::Mii::MiiManager manager;
432 auto mii = manager.BuildDefault(0); 432 auto mii = manager.BuildDefault(0);
433 433
434 // Check if mii data exist 434 if (!ValidateV3Info(mii_v3)) {
435 if (mii_v3.version == 0) {
436 return mii; 435 return mii;
437 } 436 }
438 437
@@ -576,6 +575,71 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
576 return mii_v3; 575 return mii_v3;
577} 576}
578 577
578bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
579 bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
580
581 is_valid = is_valid && (mii_v3.mii_name[0] != 0);
582
583 is_valid = is_valid && (mii_v3.mii_information.birth_month < 13);
584 is_valid = is_valid && (mii_v3.mii_information.birth_day < 32);
585 is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12);
586 is_valid = is_valid && (mii_v3.height < 128);
587 is_valid = is_valid && (mii_v3.build < 128);
588
589 is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12);
590 is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7);
591 is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12);
592 is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12);
593
594 is_valid = is_valid && (mii_v3.hair_style < 132);
595 is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8);
596
597 is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60);
598 is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6);
599 is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8);
600 is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7);
601 is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8);
602 is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13);
603 is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19);
604
605 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25);
606 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8);
607 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9);
608 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7);
609 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12);
610 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12);
611 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19);
612
613 is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18);
614 is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9);
615 is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19);
616
617 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36);
618 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5);
619 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9);
620 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7);
621 is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19);
622
623 is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6);
624 is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7);
625 is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17);
626
627 is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6);
628 is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8);
629
630 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9);
631 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6);
632 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8);
633 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21);
634
635 is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2);
636 is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9);
637 is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17);
638 is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31);
639
640 return is_valid;
641}
642
579ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) { 643ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
580 std::vector<MiiInfoElement> result; 644 std::vector<MiiInfoElement> result;
581 645
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index b68fdd54c..83ad3d343 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -24,6 +24,7 @@ public:
24 CharInfo BuildDefault(std::size_t index); 24 CharInfo BuildDefault(std::size_t index);
25 CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; 25 CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
26 Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const; 26 Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const;
27 bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
27 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); 28 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
28 Result GetIndex(const CharInfo& info, u32& index); 29 Result GetIndex(const CharInfo& info, u32& index);
29 30
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 13a843a28..046c5f18f 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -106,10 +106,10 @@ public:
106 {1, &IUser::FinalizeOld, "FinalizeOld"}, 106 {1, &IUser::FinalizeOld, "FinalizeOld"},
107 {2, &IUser::GetStateOld, "GetStateOld"}, 107 {2, &IUser::GetStateOld, "GetStateOld"},
108 {3, &IUser::IsNfcEnabledOld, "IsNfcEnabledOld"}, 108 {3, &IUser::IsNfcEnabledOld, "IsNfcEnabledOld"},
109 {400, nullptr, "Initialize"}, 109 {400, &IUser::InitializeOld, "Initialize"},
110 {401, nullptr, "Finalize"}, 110 {401, &IUser::FinalizeOld, "Finalize"},
111 {402, nullptr, "GetState"}, 111 {402, &IUser::GetStateOld, "GetState"},
112 {403, nullptr, "IsNfcEnabled"}, 112 {403, &IUser::IsNfcEnabledOld, "IsNfcEnabled"},
113 {404, nullptr, "ListDevices"}, 113 {404, nullptr, "ListDevices"},
114 {405, nullptr, "GetDeviceState"}, 114 {405, nullptr, "GetDeviceState"},
115 {406, nullptr, "GetNpadId"}, 115 {406, nullptr, "GetNpadId"},
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp
index c87da5ae4..9e06970a4 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfp/amiibo_crypto.cpp
@@ -25,7 +25,8 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
25 LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id); 25 LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id);
26 LOG_DEBUG(Service_NFP, "character_variant={}", amiibo_data.model_info.character_variant); 26 LOG_DEBUG(Service_NFP, "character_variant={}", amiibo_data.model_info.character_variant);
27 LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo_data.model_info.amiibo_type); 27 LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo_data.model_info.amiibo_type);
28 LOG_DEBUG(Service_NFP, "model_number=0x{0:x}", amiibo_data.model_info.model_number); 28 LOG_DEBUG(Service_NFP, "model_number=0x{0:x}",
29 static_cast<u16>(amiibo_data.model_info.model_number));
29 LOG_DEBUG(Service_NFP, "series={}", amiibo_data.model_info.series); 30 LOG_DEBUG(Service_NFP, "series={}", amiibo_data.model_info.series);
30 LOG_DEBUG(Service_NFP, "fixed_value=0x{0:x}", amiibo_data.model_info.constant_value); 31 LOG_DEBUG(Service_NFP, "fixed_value=0x{0:x}", amiibo_data.model_info.constant_value);
31 32
@@ -35,11 +36,12 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
35 36
36 // Validate UUID 37 // Validate UUID
37 constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3` 38 constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3`
38 if ((CT ^ ntag_file.uuid[0] ^ ntag_file.uuid[1] ^ ntag_file.uuid[2]) != ntag_file.uuid[3]) { 39 if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) !=
40 ntag_file.uuid.uid[3]) {
39 return false; 41 return false;
40 } 42 }
41 if ((ntag_file.uuid[4] ^ ntag_file.uuid[5] ^ ntag_file.uuid[6] ^ ntag_file.uuid[7]) != 43 if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^
42 ntag_file.uuid[8]) { 44 ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) {
43 return false; 45 return false;
44 } 46 }
45 47
@@ -70,7 +72,8 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
70NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { 72NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
71 NTAG215File encoded_data{}; 73 NTAG215File encoded_data{};
72 74
73 memcpy(encoded_data.uuid2.data(), nfc_data.uuid.data() + 0x8, sizeof(encoded_data.uuid2)); 75 encoded_data.uid = nfc_data.uuid.uid;
76 encoded_data.nintendo_id = nfc_data.uuid.nintendo_id;
74 encoded_data.static_lock = nfc_data.static_lock; 77 encoded_data.static_lock = nfc_data.static_lock;
75 encoded_data.compability_container = nfc_data.compability_container; 78 encoded_data.compability_container = nfc_data.compability_container;
76 encoded_data.hmac_data = nfc_data.user_memory.hmac_data; 79 encoded_data.hmac_data = nfc_data.user_memory.hmac_data;
@@ -85,7 +88,7 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
85 encoded_data.hash = nfc_data.user_memory.hash; 88 encoded_data.hash = nfc_data.user_memory.hash;
86 encoded_data.application_area = nfc_data.user_memory.application_area; 89 encoded_data.application_area = nfc_data.user_memory.application_area;
87 encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; 90 encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag;
88 memcpy(encoded_data.uuid.data(), nfc_data.uuid.data(), sizeof(encoded_data.uuid)); 91 encoded_data.lock_bytes = nfc_data.uuid.lock_bytes;
89 encoded_data.model_info = nfc_data.user_memory.model_info; 92 encoded_data.model_info = nfc_data.user_memory.model_info;
90 encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt; 93 encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt;
91 encoded_data.dynamic_lock = nfc_data.dynamic_lock; 94 encoded_data.dynamic_lock = nfc_data.dynamic_lock;
@@ -99,8 +102,9 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
99EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { 102EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
100 EncryptedNTAG215File nfc_data{}; 103 EncryptedNTAG215File nfc_data{};
101 104
102 memcpy(nfc_data.uuid.data() + 0x8, encoded_data.uuid2.data(), sizeof(encoded_data.uuid2)); 105 nfc_data.uuid.uid = encoded_data.uid;
103 memcpy(nfc_data.uuid.data(), encoded_data.uuid.data(), sizeof(encoded_data.uuid)); 106 nfc_data.uuid.nintendo_id = encoded_data.nintendo_id;
107 nfc_data.uuid.lock_bytes = encoded_data.lock_bytes;
104 nfc_data.static_lock = encoded_data.static_lock; 108 nfc_data.static_lock = encoded_data.static_lock;
105 nfc_data.compability_container = encoded_data.compability_container; 109 nfc_data.compability_container = encoded_data.compability_container;
106 nfc_data.user_memory.hmac_data = encoded_data.hmac_data; 110 nfc_data.user_memory.hmac_data = encoded_data.hmac_data;
@@ -127,10 +131,10 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
127 131
128u32 GetTagPassword(const TagUuid& uuid) { 132u32 GetTagPassword(const TagUuid& uuid) {
129 // Verifiy that the generated password is correct 133 // Verifiy that the generated password is correct
130 u32 password = 0xAA ^ (uuid[1] ^ uuid[3]); 134 u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]);
131 password &= (0x55 ^ (uuid[2] ^ uuid[4])) << 8; 135 password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8;
132 password &= (0xAA ^ (uuid[3] ^ uuid[5])) << 16; 136 password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16;
133 password &= (0x55 ^ (uuid[4] ^ uuid[6])) << 24; 137 password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24;
134 return password; 138 return password;
135} 139}
136 140
@@ -138,15 +142,13 @@ HashSeed GetSeed(const NTAG215File& data) {
138 HashSeed seed{ 142 HashSeed seed{
139 .magic = data.write_counter, 143 .magic = data.write_counter,
140 .padding = {}, 144 .padding = {},
141 .uuid1 = {}, 145 .uid_1 = data.uid,
142 .uuid2 = {}, 146 .nintendo_id_1 = data.nintendo_id,
147 .uid_2 = data.uid,
148 .nintendo_id_2 = data.nintendo_id,
143 .keygen_salt = data.keygen_salt, 149 .keygen_salt = data.keygen_salt,
144 }; 150 };
145 151
146 // Copy the first 8 bytes of uuid
147 memcpy(seed.uuid1.data(), data.uuid.data(), sizeof(seed.uuid1));
148 memcpy(seed.uuid2.data(), data.uuid.data(), sizeof(seed.uuid2));
149
150 return seed; 152 return seed;
151} 153}
152 154
@@ -165,8 +167,10 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
165 output.insert(output.end(), key.magic_bytes.begin(), 167 output.insert(output.end(), key.magic_bytes.begin(),
166 key.magic_bytes.begin() + key.magic_length); 168 key.magic_bytes.begin() + key.magic_length);
167 169
168 output.insert(output.end(), seed.uuid1.begin(), seed.uuid1.end()); 170 output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end());
169 output.insert(output.end(), seed.uuid2.begin(), seed.uuid2.end()); 171 output.emplace_back(seed.nintendo_id_1);
172 output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end());
173 output.emplace_back(seed.nintendo_id_2);
170 174
171 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++) {
172 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]));
@@ -250,14 +254,15 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou
250 reinterpret_cast<unsigned char*>(&out_data.settings)); 254 reinterpret_cast<unsigned char*>(&out_data.settings));
251 255
252 // Copy the rest of the data directly 256 // Copy the rest of the data directly
253 out_data.uuid2 = in_data.uuid2; 257 out_data.uid = in_data.uid;
258 out_data.nintendo_id = in_data.nintendo_id;
259 out_data.lock_bytes = in_data.lock_bytes;
254 out_data.static_lock = in_data.static_lock; 260 out_data.static_lock = in_data.static_lock;
255 out_data.compability_container = in_data.compability_container; 261 out_data.compability_container = in_data.compability_container;
256 262
257 out_data.constant_value = in_data.constant_value; 263 out_data.constant_value = in_data.constant_value;
258 out_data.write_counter = in_data.write_counter; 264 out_data.write_counter = in_data.write_counter;
259 265
260 out_data.uuid = in_data.uuid;
261 out_data.model_info = in_data.model_info; 266 out_data.model_info = in_data.model_info;
262 out_data.keygen_salt = in_data.keygen_salt; 267 out_data.keygen_salt = in_data.keygen_salt;
263 out_data.dynamic_lock = in_data.dynamic_lock; 268 out_data.dynamic_lock = in_data.dynamic_lock;
@@ -309,7 +314,7 @@ bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& t
309 // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! 314 // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
310 constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START; 315 constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
311 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(), 316 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
312 sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uuid), 317 sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
313 input_length, reinterpret_cast<unsigned char*>(&tag_data.hmac_tag)); 318 input_length, reinterpret_cast<unsigned char*>(&tag_data.hmac_tag));
314 319
315 // Regenerate data HMAC 320 // Regenerate data HMAC
@@ -350,7 +355,7 @@ bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_t
350 constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START; 355 constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
351 constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_START; 356 constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_START;
352 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(), 357 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
353 sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uuid), 358 sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
354 input_length, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag)); 359 input_length, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag));
355 360
356 // Init mbedtls HMAC context 361 // Init mbedtls HMAC context
@@ -364,7 +369,7 @@ bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_t
364 input_length2); // Data 369 input_length2); // Data
365 mbedtls_md_hmac_update(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag), 370 mbedtls_md_hmac_update(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag),
366 sizeof(HashData)); // Tag HMAC 371 sizeof(HashData)); // Tag HMAC
367 mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.uuid), 372 mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.uid),
368 input_length); 373 input_length);
369 mbedtls_md_hmac_finish(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data)); 374 mbedtls_md_hmac_finish(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data));
370 375
diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h
index e3fa3d07e..0175ced91 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.h
+++ b/src/core/hle/service/nfp/amiibo_crypto.h
@@ -24,8 +24,10 @@ using DrgbOutput = std::array<u8, 0x20>;
24struct HashSeed { 24struct HashSeed {
25 u16_be magic; 25 u16_be magic;
26 std::array<u8, 0xE> padding; 26 std::array<u8, 0xE> padding;
27 std::array<u8, 0x8> uuid1; 27 UniqueSerialNumber uid_1;
28 std::array<u8, 0x8> uuid2; 28 u8 nintendo_id_1;
29 UniqueSerialNumber uid_2;
30 u8 nintendo_id_2;
29 std::array<u8, 0x20> keygen_salt; 31 std::array<u8, 0x20> keygen_salt;
30}; 32};
31static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size"); 33static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size");
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
index ce3bcccf4..f0eaa7df2 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfp/nfp_device.cpp
@@ -22,6 +22,9 @@
22#include "core/hle/service/nfp/nfp_device.h" 22#include "core/hle/service/nfp/nfp_device.h"
23#include "core/hle/service/nfp/nfp_result.h" 23#include "core/hle/service/nfp/nfp_result.h"
24#include "core/hle/service/nfp/nfp_user.h" 24#include "core/hle/service/nfp/nfp_user.h"
25#include "core/hle/service/time/time_manager.h"
26#include "core/hle/service/time/time_zone_content_manager.h"
27#include "core/hle/service/time/time_zone_types.h"
25 28
26namespace Service::NFP { 29namespace Service::NFP {
27NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, 30NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
@@ -39,6 +42,9 @@ NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
39 }; 42 };
40 is_controller_set = true; 43 is_controller_set = true;
41 callback_key = npad_device->SetCallback(engine_callback); 44 callback_key = npad_device->SetCallback(engine_callback);
45
46 auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
47 current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point;
42} 48}
43 49
44NfpDevice::~NfpDevice() { 50NfpDevice::~NfpDevice() {
@@ -98,6 +104,7 @@ bool NfpDevice::LoadAmiibo(const std::vector<u8>& data) {
98 } 104 }
99 105
100 device_state = DeviceState::TagFound; 106 device_state = DeviceState::TagFound;
107 deactivate_event->GetReadableEvent().Clear();
101 activate_event->GetWritableEvent().Signal(); 108 activate_event->GetWritableEvent().Signal();
102 return true; 109 return true;
103} 110}
@@ -112,6 +119,7 @@ void NfpDevice::CloseAmiibo() {
112 device_state = DeviceState::TagRemoved; 119 device_state = DeviceState::TagRemoved;
113 encrypted_tag_data = {}; 120 encrypted_tag_data = {};
114 tag_data = {}; 121 tag_data = {};
122 activate_event->GetReadableEvent().Clear();
115 deactivate_event->GetWritableEvent().Signal(); 123 deactivate_event->GetWritableEvent().Signal();
116} 124}
117 125
@@ -140,8 +148,6 @@ void NfpDevice::Finalize() {
140} 148}
141 149
142Result NfpDevice::StartDetection(s32 protocol_) { 150Result NfpDevice::StartDetection(s32 protocol_) {
143 // TODO(german77): Add callback for when nfc data is available
144
145 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { 151 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
146 npad_device->SetPollingMode(Common::Input::PollingMode::NFC); 152 npad_device->SetPollingMode(Common::Input::PollingMode::NFC);
147 device_state = DeviceState::SearchingForTag; 153 device_state = DeviceState::SearchingForTag;
@@ -172,11 +178,9 @@ Result NfpDevice::StopDetection() {
172Result NfpDevice::Flush() { 178Result NfpDevice::Flush() {
173 auto& settings = tag_data.settings; 179 auto& settings = tag_data.settings;
174 180
175 if (settings.write_date.raw_date != settings.write_date.raw_date) { 181 const auto& current_date = GetAmiiboDate(current_posix_time);
176 // TODO: Read current system date 182 if (settings.write_date.raw_date != current_date.raw_date) {
177 settings.write_date.SetYear(2022); 183 settings.write_date = current_date;
178 settings.write_date.SetMonth(9);
179 settings.write_date.SetDay(9);
180 settings.crc_counter++; 184 settings.crc_counter++;
181 // TODO: Find how to calculate the crc check 185 // TODO: Find how to calculate the crc check
182 // settings.crc = CalculateCRC(settings); 186 // settings.crc = CalculateCRC(settings);
@@ -239,10 +243,10 @@ Result NfpDevice::GetTagInfo(TagInfo& tag_info) const {
239 } 243 }
240 244
241 tag_info = { 245 tag_info = {
242 .uuid = encrypted_tag_data.uuid, 246 .uuid = encrypted_tag_data.uuid.uid,
243 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.size()), 247 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
244 .protocol = protocol, 248 .protocol = 1,
245 .tag_type = static_cast<u32>(encrypted_tag_data.user_memory.model_info.amiibo_type), 249 .tag_type = 2,
246 }; 250 };
247 251
248 return ResultSuccess; 252 return ResultSuccess;
@@ -255,8 +259,6 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
255 } 259 }
256 260
257 const auto& settings = tag_data.settings; 261 const auto& settings = tag_data.settings;
258 const u32 application_area_size =
259 tag_data.settings.settings.appdata_initialized == 0 ? 0 : sizeof(ApplicationArea);
260 262
261 // TODO: Validate this data 263 // TODO: Validate this data
262 common_info = { 264 common_info = {
@@ -267,8 +269,8 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
267 settings.write_date.GetDay(), 269 settings.write_date.GetDay(),
268 }, 270 },
269 .write_counter = tag_data.write_counter, 271 .write_counter = tag_data.write_counter,
270 .version = 1, 272 .version = 0,
271 .application_area_size = application_area_size, 273 .application_area_size = sizeof(ApplicationArea),
272 }; 274 };
273 return ResultSuccess; 275 return ResultSuccess;
274} 276}
@@ -334,13 +336,8 @@ Result NfpDevice::SetNicknameAndOwner(const AmiiboName& amiibo_name) {
334 Service::Mii::MiiManager manager; 336 Service::Mii::MiiManager manager;
335 auto& settings = tag_data.settings; 337 auto& settings = tag_data.settings;
336 338
337 // TODO: Read current system date 339 settings.init_date = GetAmiiboDate(current_posix_time);
338 settings.init_date.SetYear(2022); 340 settings.write_date = GetAmiiboDate(current_posix_time);
339 settings.init_date.SetMonth(9);
340 settings.init_date.SetDay(9);
341 settings.write_date.SetYear(2022);
342 settings.write_date.SetMonth(9);
343 settings.write_date.SetDay(9);
344 settings.crc_counter++; 341 settings.crc_counter++;
345 // TODO: Find how to calculate the crc check 342 // TODO: Find how to calculate the crc check
346 // settings.crc = CalculateCRC(settings); 343 // settings.crc = CalculateCRC(settings);
@@ -570,4 +567,23 @@ void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo
570 } 567 }
571} 568}
572 569
570AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const {
571 const auto& time_zone_manager =
572 system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
573 Time::TimeZone::CalendarInfo calendar_info{};
574 AmiiboDate amiibo_date{};
575
576 amiibo_date.SetYear(2000);
577 amiibo_date.SetMonth(1);
578 amiibo_date.SetDay(1);
579
580 if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) {
581 amiibo_date.SetYear(calendar_info.time.year);
582 amiibo_date.SetMonth(calendar_info.time.month);
583 amiibo_date.SetDay(calendar_info.time.day);
584 }
585
586 return amiibo_date;
587}
588
573} // namespace Service::NFP 589} // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
index 9ceb7b8fd..c020506a6 100644
--- a/src/core/hle/service/nfp/nfp_device.h
+++ b/src/core/hle/service/nfp/nfp_device.h
@@ -75,6 +75,7 @@ private:
75 75
76 AmiiboName GetAmiiboName(const AmiiboSettings& settings) const; 76 AmiiboName GetAmiiboName(const AmiiboSettings& settings) const;
77 void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name); 77 void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
78 AmiiboDate GetAmiiboDate(s64 posix_time) const;
78 79
79 bool is_controller_set{}; 80 bool is_controller_set{};
80 int callback_key; 81 int callback_key;
@@ -88,6 +89,7 @@ private:
88 89
89 bool is_data_moddified{}; 90 bool is_data_moddified{};
90 s32 protocol{}; 91 s32 protocol{};
92 s64 current_posix_time{};
91 DeviceState device_state{DeviceState::Unavailable}; 93 DeviceState device_state{DeviceState::Unavailable};
92 94
93 NTAG215File tag_data{}; 95 NTAG215File tag_data{};
diff --git a/src/core/hle/service/nfp/nfp_result.h b/src/core/hle/service/nfp/nfp_result.h
index 15bc02b15..ac259e2ff 100644
--- a/src/core/hle/service/nfp/nfp_result.h
+++ b/src/core/hle/service/nfp/nfp_result.h
@@ -17,5 +17,6 @@ constexpr Result ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
17constexpr Result CorruptedData(ErrorModule::NFP, 144); 17constexpr Result CorruptedData(ErrorModule::NFP, 144);
18constexpr Result WrongApplicationAreaId(ErrorModule::NFP, 152); 18constexpr Result WrongApplicationAreaId(ErrorModule::NFP, 152);
19constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168); 19constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168);
20constexpr Result NotAnAmiibo(ErrorModule::NFP, 178);
20 21
21} // namespace Service::NFP 22} // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 2685ae8fe..448791846 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -75,11 +75,19 @@ enum class AmiiboSeries : u8 {
75 Diablo, 75 Diablo,
76}; 76};
77 77
78using TagUuid = std::array<u8, 10>; 78using UniqueSerialNumber = std::array<u8, 7>;
79using LockBytes = std::array<u8, 2>;
79using HashData = std::array<u8, 0x20>; 80using HashData = std::array<u8, 0x20>;
80using ApplicationArea = std::array<u8, 0xD8>; 81using ApplicationArea = std::array<u8, 0xD8>;
81using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; 82using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
82 83
84struct TagUuid {
85 UniqueSerialNumber uid;
86 u8 nintendo_id;
87 LockBytes lock_bytes;
88};
89static_assert(sizeof(TagUuid) == 10, "TagUuid is an invalid size");
90
83struct AmiiboDate { 91struct AmiiboDate {
84 u16 raw_date{}; 92 u16 raw_date{};
85 93
@@ -91,7 +99,7 @@ struct AmiiboDate {
91 return static_cast<u16>(((GetValue() & 0xFE00) >> 9) + 2000); 99 return static_cast<u16>(((GetValue() & 0xFE00) >> 9) + 2000);
92 } 100 }
93 u8 GetMonth() const { 101 u8 GetMonth() const {
94 return static_cast<u8>(((GetValue() & 0x01E0) >> 5) - 1); 102 return static_cast<u8>((GetValue() & 0x01E0) >> 5);
95 } 103 }
96 u8 GetDay() const { 104 u8 GetDay() const {
97 return static_cast<u8>(GetValue() & 0x001F); 105 return static_cast<u8>(GetValue() & 0x001F);
@@ -102,7 +110,7 @@ struct AmiiboDate {
102 raw_date = Common::swap16((GetValue() & ~0xFE00) | year_converted); 110 raw_date = Common::swap16((GetValue() & ~0xFE00) | year_converted);
103 } 111 }
104 void SetMonth(u8 month) { 112 void SetMonth(u8 month) {
105 const u16 month_converted = static_cast<u16>((month + 1) << 5); 113 const u16 month_converted = static_cast<u16>(month << 5);
106 raw_date = Common::swap16((GetValue() & ~0x01E0) | month_converted); 114 raw_date = Common::swap16((GetValue() & ~0x01E0) | month_converted);
107 } 115 }
108 void SetDay(u8 day) { 116 void SetDay(u8 day) {
@@ -137,7 +145,7 @@ struct AmiiboModelInfo {
137 u16 character_id; 145 u16 character_id;
138 u8 character_variant; 146 u8 character_variant;
139 AmiiboType amiibo_type; 147 AmiiboType amiibo_type;
140 u16 model_number; 148 u16_be model_number;
141 AmiiboSeries series; 149 AmiiboSeries series;
142 u8 constant_value; // Must be 02 150 u8 constant_value; // Must be 02
143 INSERT_PADDING_BYTES(0x4); // Unknown 151 INSERT_PADDING_BYTES(0x4); // Unknown
@@ -172,7 +180,7 @@ struct EncryptedAmiiboFile {
172static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); 180static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size");
173 181
174struct NTAG215File { 182struct NTAG215File {
175 std::array<u8, 0x2> uuid2; 183 LockBytes lock_bytes; // Tag UUID
176 u16 static_lock; // Set defined pages as read only 184 u16 static_lock; // Set defined pages as read only
177 u32 compability_container; // Defines available memory 185 u32 compability_container; // Defines available memory
178 HashData hmac_data; // Hash 186 HashData hmac_data; // Hash
@@ -188,7 +196,8 @@ struct NTAG215File {
188 HashData hash; // Probably a SHA256-HMAC hash? 196 HashData hash; // Probably a SHA256-HMAC hash?
189 ApplicationArea application_area; // Encrypted Game data 197 ApplicationArea application_area; // Encrypted Game data
190 HashData hmac_tag; // Hash 198 HashData hmac_tag; // Hash
191 std::array<u8, 0x8> uuid; 199 UniqueSerialNumber uid; // Unique serial number
200 u8 nintendo_id; // Tag UUID
192 AmiiboModelInfo model_info; 201 AmiiboModelInfo model_info;
193 HashData keygen_salt; // Salt 202 HashData keygen_salt; // Salt
194 u32 dynamic_lock; // Dynamic lock 203 u32 dynamic_lock; // Dynamic lock
@@ -215,7 +224,8 @@ static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>,
215 "EncryptedNTAG215File must be trivially copyable."); 224 "EncryptedNTAG215File must be trivially copyable.");
216 225
217struct TagInfo { 226struct TagInfo {
218 TagUuid uuid; 227 UniqueSerialNumber uuid;
228 INSERT_PADDING_BYTES(0x3);
219 u8 uuid_length; 229 u8 uuid_length;
220 INSERT_PADDING_BYTES(0x15); 230 INSERT_PADDING_BYTES(0x15);
221 s32 protocol; 231 s32 protocol;