Changes

5,694 bytes added ,  22:35, 17 October 2019
Did a lot of research on layer 3 packets by sniffing the connection between the NFC adapter and the 3DS using an IRda usb adapter. Been able to spoof the nfc adapter using the same adapter (see github link at bottom of page)
Line 1: Line 1: −
The Nintendo NFC adapter is an upcoming external device which adds NFC capabilities for [[amiibo]]s to old Nintendo 3DS and Nintendo 2DS consoles, using the infrared port on the back of the console.
+
The Nintendo NFC adapter, formally '''Nintendo NFC Reader/Writer'''  and codenamed '''Fangate''', is an external device which adds NFC capabilities for [[amiibo]]s to old Nintendo 3DS and Nintendo 2DS consoles, using the infrared port on the back of the console.
 +
 
 +
It launched simultaneously with Animal Crossing Happy Home Designer, with which it's optionally bundled; it can also be bought standalone at a nominal price of 21 €.
    
[[File:150217nfcreader-640x360.jpg|thumb|right|250px|Media preview, as released by Nintendo]]
 
[[File:150217nfcreader-640x360.jpg|thumb|right|250px|Media preview, as released by Nintendo]]
Line 7: Line 9:  
Based on analysis of the [[fangate_updater.bin]] file, which is part of the old Nintendo 3DS operating system since [[9.3.0-21]] and contains the firmware running on the external adapter; and analysis of the [[NFC Services]] running on old 3DS.
 
Based on analysis of the [[fangate_updater.bin]] file, which is part of the old Nintendo 3DS operating system since [[9.3.0-21]] and contains the firmware running on the external adapter; and analysis of the [[NFC Services]] running on old 3DS.
   −
* SOC inside the adapter: Broadcom BCM20791B1
+
* SOC inside the adapter: Broadcom BCM20791B1 or ST proprietary "MCU-FGT/rev.A/GH24S VQ"
 
* CPU: ARM Cortex M0
 
* CPU: ARM Cortex M0
 
* Communications: infrared, with [[ir:USER]] running on the console. Uses obfuscated payloads. Baud rate is 115200 bps.
 
* Communications: infrared, with [[ir:USER]] running on the console. Uses obfuscated payloads. Baud rate is 115200 bps.
Line 146: Line 148:  
uint16_t * plain = (uint16_t *) voidplain;
 
uint16_t * plain = (uint16_t *) voidplain;
 
uint16_t * cipher = (uint16_t *) voidcipher;
 
uint16_t * cipher = (uint16_t *) voidcipher;
size_t halfCount = size / sizeof(uint16_t);
+
size_t halfCount = size >> 1; // Divide by 2 rounding towards zero
    
uint16_t xorval = htobe16(0xE963);
 
uint16_t xorval = htobe16(0xE963);
Line 160: Line 162:  
uint16_t * cipher = (uint16_t *) voidcipher;
 
uint16_t * cipher = (uint16_t *) voidcipher;
 
uint16_t * plain = (uint16_t *) voidplain;
 
uint16_t * plain = (uint16_t *) voidplain;
size_t halfCount = size / sizeof(uint16_t);
+
size_t halfCount = size >> 1; // Divide by 2 rounding towards zero
   −
if (halfCount) {
+
uint16_t xorval = htobe16(0xE963);
size_t i;
+
size_t i;
for (i = halfCount - 1; i > 0; i--) {
  −
plain[i] = cipher[i] ^ cipher[i - 1];
  −
}
     −
plain[0] = cipher[0] ^ htobe16(0xE963);
+
for (i = 0; i < halfCount; i++) {
 +
uint16_t word = plain[i];
 +
cipher[i] = xorval ^ word;
 +
xorval = word;
 
}
 
}
 
}</nowiki>
 
}</nowiki>
Line 206: Line 208:  
|-
 
|-
 
! 0x05
 
! 0x05
| colspan="8"|Connection identifier
+
| colspan="8"|Connection identifier of master (3DS), value determined by master
 
|-
 
|-
 
! 0x06
 
! 0x06
| colspan="8"|Reserved for future use?
+
| colspan="8"|Connection identifier of slave (NFC adapter), value determined by slave
 
|-
 
|-
 
! 0x07
 
! 0x07
Line 219: Line 221:  
|}
 
|}
   −
* Random values are generated using a Mersenne Twister whose seed is based off the NFC adapter system tick counter. It is therefore random, and the 3DS won't attempt to validate them by any means. Its purpose is unknown.
+
* Random values are generated using a Mersenne Twister whose seed is based off the NFC adapter system tick counter. It is therefore random, and the 3DS won't attempt to validate them by any means. Its purpose is to make every encrypted packet look completely different to the previous one. This makes a replay attack impossible without knowing the encryption algorithm.
 
* NFC adapter will ignore packets whose protocol version is not 1. It will not even reply.
 
* NFC adapter will ignore packets whose protocol version is not 1. It will not even reply.
* Connection identifier is a random byte the 3DS assigns to identify the connection should be several connections in range at once. Slave devices must save this value from the initial handshake packet and use it for replies. It must also ignore packets whose connection ID does not match.
+
* Connection identifier is a random byte the 3DS assigns to identify the connection should there be several connections in range at once. Slave devices must save this value from the initial handshake packet and use it for replies. The 3DS will also save the connection identifier byte of the slave which is also random. The 3DS must also ignore packets whose connection ID does not match.
    
=== Operation codes ===
 
=== Operation codes ===
Line 231: Line 233:  
|-
 
|-
 
! 0x0
 
! 0x0
| Layer 3 command?
+
| Layer 3 command
 
| style="background: green" | Yes
 
| style="background: green" | Yes
 
| Master to slave
 
| Master to slave
Line 300: Line 302:  
|}
 
|}
    +
== Layer 3 ==
 +
Layer 3 is the payload of layer 2. A lot is unknown of this layer and thus a lot of assumptions were made in the following tables.
 +
 +
Layer 3 contains the following data:
 +
{| class="wikitable" style="margin: 0 auto; text-align: center;"
 +
! style="border-top: none" | Byte
 +
! style="width:10%;"| 7
 +
! style="width:10%;"| 6
 +
! style="width:10%;"| 5
 +
! style="width:10%;"| 4
 +
! style="width:10%;"| 3
 +
! style="width:10%;"| 2
 +
! style="width:10%;"| 1
 +
! style="width:10%;"| 0
 +
|-
 +
! 0x00
 +
| colspan="4"|Request identifier nibble
 +
| colspan="4"|Always <code>0x1</code>
 +
|-
 +
! 0x01
 +
| colspan="8"|Slave/master identifier byte
 +
|-
 +
! 0x02
 +
| colspan="8"|Request type code upper byte
 +
|-
 +
! 0x03
 +
| colspan="8"|Request type code lower byte
 +
|-
 +
! 0x04+
 +
| colspan="8" style="background:#ffd0d0;"|Payload (if any)
 +
|}
 +
*Request identifier nibble is incremented by <code>0x1</code> at every new request by the master, the same value for this byte is also sent by the slave in response to the request of the master
 +
*Slave/master identifier byte is <code>0x1</code> for a message from the master and <code>0x10</code> for a message from the slave
 +
 +
=== Request type codes ===
 +
{| class="wikitable"
 +
! Code
 +
! Request description
 +
! Direction
 +
! Has payload
 +
|-
 +
! 0x0000
 +
| ACK
 +
| Slave to master
 +
| style="background: green" | Yes
 +
|-
 +
! 0x0003
 +
| Get firmware version and battery level of NFC adapter
 +
| Master to slave
 +
| style="background: red" | No
 +
|-
 +
! 0x0004
 +
| Firmware version and battery level
 +
| Slave to master
 +
| style="background: green" | Yes
 +
|-
 +
! 0x0100
 +
| Unknown, slave always responds with ACK
 +
| Master to slave
 +
| style="background: green" | Yes
 +
|-
 +
! 0x0202
 +
| Request to stop communication with NFC tag
 +
| Master to slave
 +
| style="background: red" | No
 +
|-
 +
! 0x0204
 +
| Get dumped data from NFC tag
 +
| Master to slave
 +
| style="background: red" | No
 +
|-
 +
! 0x0205
 +
| Data from NFC tag
 +
| Slave to master
 +
| style="background: green" | Yes
 +
|-
 +
! 0x0206
 +
| Request to start communication with NFC tag
 +
| Master to slave
 +
| style="background: green" | Yes
 +
|-
 +
! 0x0207
 +
| Request to write data to NFC tag
 +
| Master to slave
 +
| style="background: green" | Yes
 +
|}
 +
=== Payload ===
 +
==== 0x0000 ====
 +
Acknowledgement message always send by slave. Payload always contains <code>0x000000AA</code>
 +
==== 0x0004 ====
 +
Payload contains firmware version and battery level of NFC adapter. Payload has a size of 6 bytes.
 +
{| class="wikitable" style="margin: 0 auto; text-align: center;"
 +
! style="border-top: none" | Byte
 +
! style="width:10%;"| 7
 +
! style="width:10%;"| 6
 +
! style="width:10%;"| 5
 +
! style="width:10%;"| 4
 +
! style="width:10%;"| 3
 +
! style="width:10%;"| 2
 +
! style="width:10%;"| 1
 +
! style="width:10%;"| 0
 +
|-
 +
! 0x00
 +
| colspan="8"|Upper or lower byte of version number, newest firmware is <code>0x1</code>
 +
|-
 +
! 0x01
 +
| colspan="8"|Upper or lower byte of version number, newest firmware is <code>0x6</code>
 +
|-
 +
! 0x02
 +
| colspan="8"|Padding byte? Always <code>0x0</code>
 +
|-
 +
! 0x03
 +
| colspan="8"|Padding byte? Always <code>0x0</code>
 +
|-
 +
! 0x04
 +
| colspan="8"|Battery level. Values varies between <code>0x3</code> for full battery and <code>0x0</code> for empty
 +
|-
 +
! 0x05
 +
| colspan="8"|Padding byte? Always <code>0x0</code>
 +
|}
 +
*NFC reader LED already turns red when the battery level byte is <code>0x2</code>, this will also trigger a low battery level warning on the 3DS
 +
==== 0x0100 ====
 +
The purpose of this request by the master is unknown. Slave always responds with ACK. Payload of this request is always <code>0x0003E8AA</code>
 +
==== 0x0205 ====
 +
Payload contains data regarding NFC communication. The first byte of the payload means the following:
 +
{| class="wikitable"
 +
! style="border-top: none" | Code
 +
! Description
 +
|-
 +
! 0x00
 +
| colspan="8"|NFC communication is stopped as a result of a <code>0x0202</code> request by the master
 +
|-
 +
! 0x01
 +
| colspan="8"|No NFC tag on top of the reader
 +
|-
 +
! 0x02
 +
| colspan="8"|Busy dumping NFC tag
 +
|-
 +
! 0x03
 +
| colspan="8"|NFC tag dump after write by master
 +
|-
 +
! 0x04
 +
| colspan="8"|NFC tag fully dumped
 +
|-
 +
! 0x05
 +
| colspan="8"|NFC tag dump after write by master
 +
|-
 +
! 0x07
 +
| colspan="8"|NFC tag not a NTAG215 or contains no Amiibo compatible data
 +
|-
 +
! 0x08
 +
| colspan="8"|NFC tag removed from reader
 +
|}
 +
*After the tag is written by the master and dumped again, the first few dumps start with 0x03, this changes to 0x05 after a few dumps. The reason for this is unknown
 +
==== 0x0206 ====
 +
Request from master to start NFC communication. Payload always contains 19 <code>0x0</code> padding bytes, followed by <code>0xC80300393A737486000001</code> and another 26 <code>0x0</code> padding bytes.
 +
==== 0x0207 ====
 +
Request from master to write to NFC tag. The request packet already contains the desired data to be written to the tag. Payload start with two <code>0x00</code> padding bytes followed by the 7 ID bytes of the tag. These ID bytes are used by the NFC adapter to check if same Amiibo is placed on the NFC adapter again.
 
== Samples ==
 
== Samples ==
   Line 444: Line 604:  
= External links =
 
= External links =
 
* [https://www.broadcom.com/products/NFC/NFC-Solutions/BCM2079x-Family BCM2079x brief on Broadcom's website]
 
* [https://www.broadcom.com/products/NFC/NFC-Solutions/BCM2079x-Family BCM2079x brief on Broadcom's website]
 +
* [https://github.com/HubSteven/3ds_ir/ Python scripts to sniff and spoof IR communication between the NFC reader and 3DS using an IRda adapter]
1

edit