summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nwm/uds_data.h
blob: 76e8f546b5a87db489c58d9a1492e7e8608e3bf1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <vector>
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/service.h"

namespace Service {
namespace NWM {

enum class SAP : u8 { SNAPExtensionUsed = 0xAA };

enum class PDUControl : u8 { UnnumberedInformation = 3 };

enum class EtherType : u16 { SecureData = 0x876D, EAPoL = 0x888E };

/*
 * 802.2 header, UDS packets always use SNAP for these headers,
 * which means the dsap and ssap are always SNAPExtensionUsed (0xAA)
 * and the OUI is always 0.
 */
struct LLCHeader {
    u8 dsap = static_cast<u8>(SAP::SNAPExtensionUsed);
    u8 ssap = static_cast<u8>(SAP::SNAPExtensionUsed);
    u8 control = static_cast<u8>(PDUControl::UnnumberedInformation);
    std::array<u8, 3> OUI = {};
    u16_be protocol;
};

static_assert(sizeof(LLCHeader) == 8, "LLCHeader has the wrong size");

/*
 * Nintendo SecureData header, every UDS packet contains one,
 * it is used to store metadata about the transmission such as
 * the source and destination network node ids.
 */
struct SecureDataHeader {
    // TODO(Subv): It is likely that the first 4 bytes of this header are
    // actually part of another container protocol.
    u16_be protocol_size;
    INSERT_PADDING_BYTES(2);
    u16_be securedata_size;
    u8 is_management;
    u8 data_channel;
    u16_be sequence_number;
    u16_be dest_node_id;
    u16_be src_node_id;
};

static_assert(sizeof(SecureDataHeader) == 14, "SecureDataHeader has the wrong size");

/*
 * The raw bytes of this structure are the CTR used in the encryption (AES-CTR)
 * process used to generate the CCMP key for data frame encryption.
 */
struct DataFrameCryptoCTR {
    u32_le wlan_comm_id;
    u32_le network_id;
    std::array<u8, 6> host_mac;
    u16_le id;
};

static_assert(sizeof(DataFrameCryptoCTR) == 16, "DataFrameCryptoCTR has the wrong size");

constexpr u16 EAPoLStartMagic = 0x201;

/*
 * Nintendo EAPoLStartPacket, is used to initaliaze a connection between client and host
 */
struct EAPoLStartPacket {
    u16_be magic = EAPoLStartMagic;
    u16_be association_id;
    // This value is hardcoded to 1 in the NWM module.
    u16_be unknown = 1;
    INSERT_PADDING_BYTES(2);

    u64_be friend_code_seed;
    std::array<u16_be, 10> username;
    INSERT_PADDING_BYTES(4);
    u16_be network_node_id;
    INSERT_PADDING_BYTES(6);
};

static_assert(sizeof(EAPoLStartPacket) == 0x30, "EAPoLStartPacket has the wrong size");

/**
 * Generates an unencrypted 802.11 data payload.
 * @returns The generated frame payload.
 */
std::vector<u8> GenerateDataPayload(const std::vector<u8>& data, u8 channel, u16 dest_node,
                                    u16 src_node, u16 sequence_number);

/*
 * Generates an unencrypted 802.11 data frame body with the EAPoL-Start format for UDS
 * communication.
 * @returns The generated frame body.
 */
std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info);

} // namespace NWM
} // namespace Service