RCD

From Nintendo Switch Brew
Revision as of 16:23, 26 February 2021 by CFSworks (talk | contribs) (Document RCD handshake)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

RCD is a framework that manages remote controlled devices - RC toys that connect to the Nintendo Switch via 802.11 ("WiFi") link. The first (and currently only) released product to use this framework is Mario Kart Live: Home Circuit.

RCD devices must be paired to the host Switch system in some way (e.g. QR code) and contain the connection settings in non-volatile memory so that they can reconnect on next use without needing to repeat the pairing process.

The RCD framework implements a very simple TCP-based RPC protocol that allows an RCD client to invoke methods on an RCD server. Note that multiple such connections may be established between the Switch and device.

RCD RPC

A client connects to a TCP server and sends as many commands as it likes, one at a time (and reading the response after each), before tearing down the TCP connection. It is not valid for a client to send a response to a server or for a server to send a request to a client.

Commands have a 0x10-byte header, followed by a payload of any size up to some maximum (typically 0x1000). All numbers are represented in big-endian format.

Offset Size Description
0x0 0x2 Service being accessed
0x2 0x2 Command being invoked on that service
0x4 0x4 Payload length (PLEN)
0x8 0x4 Status code; ignored (and set to 0) for requests, an error code for responses
0xC 0x1 Flags; currently only the 1s bit is significant: it indicates a response
0xD 0x3 Padding; zero.
0x10 PLEN The parameters to the command, or the response

In theory, multiple "services" could be multiplexed over a single TCP connection, but in practice only a single service is allowed per TCP port.

Handshake protocol

Service ID: 0x0001
Commands: 4

When a device first establishes a wireless connection, it connects to the Switch on a well-known port to access the "handshake" service and make its presence known. A successful handshake causes application-specific RCD connections to be established. Commands must be sent in order (and no more than once), or error code 0x810e8 is generated by the host.

Command 0x1: Begin handshake

Command 0x1 input+output payload
Offset Size Description
0x0 0x10 Handshake protocol version; one byte followed by zero-padding. Must be 1.
0x10 0x10 Device "name" (e.g. 'Fuji'), followed by zero-padding. The Switch uses the empty string.
0x20 0x10 Device identifier. Devices embed their MAC as the last 6 bytes; host seems to use a randomly-generated UUID.
0x30 0x20 Nonce; cryptographic random bytes with no special purpose.

This command is sent first (by the device). The host responds in kind. Error code 0x800e8 is generated if the handshake version is not 1.

Command 0x2: Version negotiation

Command 0x2 input payload
Offset Size Description
0x0 0x20 Pairing identifier
0x20 0x1 Number of versions offered
0x21 Varies One 8-bit integer per version offered. There is no padding.
Command 0x2 output payload
Offset Size Description
0x0 0x20 Pairing identifier
0x20 0x1 Selected version
0x21 0xF Zero-padding

There are a few moving parts here.

Firstly, this command is responsible for negotiating a version for the underlying protocols. The host looks at all versions offered by the device and selects the newest version that it recognizes. Error code 0x820e8 is sent if no (recognized) versions are offered.

Secondly, the device sends its "pairing identifier," if it recognizes the name/identifier of the host (from command 0x1). If the device does not recognize the host, it sends all-zeroes instead. If the host recognizes the pairing identifier for the device, it sends that same identifier back and expects command 0x4 next (and command 0x3, if sent, will result in error code 0x810e8). If the host doesn't recognize the identifier, it will either send error code 0x850e8 (if it isn't expecting to pair) or send a randomly-generated identifier and expect command 0x3 next.

Command 0x3: Get secret key

Command 0x3 input payload
Offset Size Description
0x0 0x20 Unknown; always all zeroes?
Command 0x3 output payload
Offset Size Description
0x0 0x40 Secret key

When a new pairing is being established (see command 0x2), this is used to request the secret key generated for the pairing. It's currently unknown what purpose this "secret key" has.

When not expected (including when the RCD host isn't set up for pairing), it generates error code 0x810e8.

Command 0x4: Finalize

Command 0x4 input payload
Offset Size Description
0x0 0x20 SHA256 of all payloads (not headers) up to this point after truncation to a multiple of 0x40 bytes.
Command 0x4 output payload
Offset Size Description
0x0 0x20 SHA256 of all payloads (not headers) up to this point, including the input to this command.

This is used to finalize the handshake. SHA256 hashes of the handshake up to this point are exchanged, as an integrity check. If the client sends the wrong hash, error code 0x830e8 is sent. If the device sends the correct hash, the host responds with its own hash, and carries on with using the device.

If the device accepts the response, it leaves the channel open, and activates other network services for the host to use. If the device rejects the response, it closes the channel, resets its networking stack, and attempts the connection again from scratch. Closing the handshake channel at any point afterward will trigger this same behavior.