Home docs pia LDN
Post

LDN

This page describes the wireless protocol that is used to communicate with nearby consoles in LDN mode, which is the default mode for local multiplayer on Nintendo Switch.

Unless specified otherwise, everything is encoded in big-endian byte order.

Overview

LDN enables communication between nearby consoles. LDN operates at the data link layer, so it requires a good understanding of the IEEE 802.11 specification.

The host of the session acts as an access point and broadcasts a vendor-specific action frame every 100 milliseconds. To find nearby consoles, the console scans for these action frames. During host migration the network is destroyed and a new network is created by the new host, after which all consoles reconnect.

Also see: Local Wireless Communication on PC.

Changelog

System versionLDN versionChanges
2.0.0 - 5.1.02Initial version
6.0.0 - 17.0.13Challenge was added to authentication frame

WLAN Channels

The channel on which LDN operates can be specified by games. Allowed channels are:

BandChannels
2.4 GHz1, 6, 11
5 GHz36, 40, 44, 48

By default, LDN operates on one of the channels of the 2.4 GHz band (chosen arbitrarily).

During scanning, Nintendo uses a dwell time of 110 milliseconds.

SSID

The SSID of the network contains 32 random hex digits. The network is hidden from other devices by zeroing the SSID in the beacon frame. To find the SSIDs of nearby networks, the console scans for advertisement frames.

Authentication

When a suitable network has been found (by scanning for advertisement frames on a given set of channels) the console may try to join the network, but Nintendo uses a custom authentication procedure:

  1. The console joins the network using the open system authentication method. This is standard.
  2. The console sends an encrypted authentication request to the access point. If the console does not send an authentication request within 5 seconds after step 1, the access point disassociates the console from the network.
  3. The access point verifies the authentication request and sends an authentication response back to the console. If the console does not receive an authentication response from the access point within 700 milliseconds it resends the authentication request. After three attempts it gives up.
  4. The console verifies the authentication response. If it is valid, and indicates success, the console is now part of the network and may communicate with other consoles.

Encryption Keys

LDN supports three different security levels:

  1. Both advertisement frames and data frames are encrypted.
  2. Advertisement frames are encrypted, data frames are plaintext.
  3. Advertisement frames and data frames are both plaintext.

The security level is specified during network creation and is broadcasted as part of the advertisement frame. In practice, the security level will always be set to 1, because security level 2 and 3 are only allowed during development.

Given a 16-byte input key and a buffer of arbitrary size, encryption keys are derived as follows:

  1. aes_kek_generation_source is decrypted with master key generation 0.
  2. The input key is decrypted with the key from step 1.
  3. aes_key_generation_source is decrypted with the key from step 2.
  4. The first 16 bytes of the SHA-256 hash of the input buffer are decrypted with the key from step 3.

For data frames, the input key is f1e7018419a84f711da714c2cf919c9c and the input buffer looks as follows:

OffsetSizeDescription
0x016Network key (generated when the network is created)
0x10NPassword specified by game (optional, up to 64 bytes)

For advertisement frames, see below.

IP Stack

When a console joins the network, the access point immediately assigns it an unused IP address. After joining the network, the console reads its own IP address and the IP addresses of the other consoles from the next advertisement frame. It then keeps monitoring advertisement frames to get notified when a console joins or leaves the network.

IP addresses are of the form 169.254.X.Y where X is a randomly generated during network creation, and Y is assigned to each station by the host. Because the host is always the first participant of the network, its IP address is always 169.254.X.1. The broadcast address is 169.254.X.255.

This is a vendor-specific action frame that is broadcasted by the access point every 100 milliseconds.

OffsetSizeDescription
0x01Category (127 = vendor-specific)
0x13OUI (00:22:AA)
0x41Protocol id (4 = LDN)
0x51Padding (always 0)
0x62Packet type (257 = advertisement)
0x82Must be 0
0xA2Padding (always 0)
0xC Advertisement payload
OffsetSizeDescription
0x032Session info
0x201LDN version
0x211Encryption type (1=plain, 2=AES-CTR)
0x222Advertisement data size
0x244Nonce for AES-CTR algorithm
0x2832SHA-256 hash, calculated over the whole advertisement payload with the hash set to zero
0x48 Advertisement data

If encryption is enabled, the hash and advertisement data are encrypted with AES-CTR. The input buffer for key derivation is the session info, and the input key is 191884743e24c77d87c69e4207d0c438.

OffsetSizeDescription
0x016Network key
0x102Security level
0x121Station accept policy:
0 = Open participation
1 = Closed participation
2 = Blacklist (provided by game)
3 = Whitelist (provided by game)
0x133Padding (always 0)
0x161Maximum number of participants
0x171Current number of participants
0x1856 x 8Participant list
0x1D82Padding (always 0)
0x1DA2Application data size
0x1DC384Application data
0x35C412Padding (always 0)
0x4F88Authentication token (random)

The authentication token is generated when the network is created and was added in LDN version 3. In previous versions it is set to 0. It is used during authentication.

Participant Info

OffsetSizeDescription
0x04IP address
0x46MAC address
0xA1Is connected
0xB1Padding (always 0)
0xC32Username
0x2C2Application communication version
0x2E10Padding (always 0)

Authentication Frame

This is a data frame with ethertype 0x88B7 (OUI extended). It is usually encrypted.

OffsetSizeDescription
0x03OUI (00:22:AA)
0x32Packet type (258 = authentication)
0x51Padding (always 0)
0x6 Authentication data

Authentication Data

OffsetSizeDescription
0x01LDN version
0x11Payload size (size & 0xFF)
0x21Status code
0x310 = request, 1 = response
0x41Payload size (size >> 8)
0x53Padding (always 0)
0x832Session info in little-endian byte order
0x2816Network key
0x3816Authentication key (random bytes)
0x48 Authentication payload (request or response)

Authentication Status Code

This is set to 0 in an authentication request. In an authentication response, it is set to one of the following values:

ValueDescription
0Success
1Participation denied by policy
2Malformed authentication request
4Authentication request has invalid version number
5Authentication request is unexpected
6Authentication challenge is invalid

Authentication Request

OffsetSizeDescription
0x032Username
0x202Application communication version
0x2230Padding (always 0)

LDN version 3 and later:

OffsetSizeDescription
0x400x24Always 0
0x640x300Authentication challenge (only present if enabled)

The challenge is always enabled for games, but not for system titles.

Authentication Response

LDN version 3 and later:

OffsetSizeDescription
0x00x84Unknown
0x840x100Challenge response (only present if enabled)

Challenge Request

The challenge was added to the authentication frame in LDN version 3. Its purpose is to make sure that the game was purchased separately on all communicating consoles. If a single purchase is used on multiple consoles, an error dialog is shown.

OffsetSizeDescription
0x04Always 0
0x432HMAC-SHA256
0x2412Always 0
0x301Always 0
0x311Always 0
0x321P
0x331Q
0x341Debug check (always 0)
0x353Padding (always 0)
0x388Authentication token (see advertisement frame)
0x408Authentication nonce (random)
0x488Device id
0x500x70Always 0
0xC00x40Unknown (8*P bytes)
0x1000x200Unknown (8*Q bytes)

The HMAC is calculated over bytes 0x30 - 0x300 and the key is f84b487fb37251c263bf11609036589266af70ca79b44c93c7370c5769c0f602.

Challenge Response

OffsetSizeDescription
0x04Always 0
0x432HMAC-SHA256
0x2412Always 0
0x301Always 0
0x311Always 0
0x326Padding (always 0)
0x388Authentication nonce from request
0x408Device id from request
0x488Own device id
0x500xB0Always 0

The HMAC is calculated over bytes 0x30 - 0x100 and the key is f84b487fb37251c263bf11609036589266af70ca79b44c93c7370c5769c0f602.

Disconnect Frame

This is a data frame with ethertype 0x88B7 (OUI extended). It is usually encrypted. This frame is sent when the access point disconnects a station from the network.

OffsetSizeDescription
0x03OUI (00:22:AA)
0x32Packet type (259 = disconnect)
0x51Padding (always 0)
0x6 Disconnect data

Disconnect Data

OffsetSizeDescription
0x01Disconnect reason
0x131Unused (always 0)

Disconnect Reason

ValueDescription
3Network is destroyed by host
4Network is destroyed forcefully (e.g. when the host closes the game during a match)
5Station is rejected by host

Session Info

OffsetSizeDescription
0x08Local communication id (usually the title id)
0x82Padding (always 0)
0xA2Game mode
0xC4Padding (always 0)
0x1016SSID (random bytes)
Contents