mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Services/UDS: Implement DecryptBeaconData.
This function decrypts the encrypted data tags contained in the 802.11 beacon frames.
This commit is contained in:
		
							parent
							
								
									3df85a103a
								
							
						
					
					
						commit
						d7d0b46fc1
					
				@ -422,6 +422,102 @@ static void SetApplicationData(Interface* self) {
 | 
				
			|||||||
    rb.Push(RESULT_SUCCESS);
 | 
					    rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * NWM_UDS::DecryptBeaconData service function.
 | 
				
			||||||
 | 
					 * Decrypts the encrypted data tags contained in the 802.11 beacons.
 | 
				
			||||||
 | 
					 *  Inputs:
 | 
				
			||||||
 | 
					 *      1 : Input network struct buffer descriptor.
 | 
				
			||||||
 | 
					 *      2 : Input network struct buffer ptr.
 | 
				
			||||||
 | 
					 *      3 : Input tag0 encrypted buffer descriptor.
 | 
				
			||||||
 | 
					 *      4 : Input tag0 encrypted buffer ptr.
 | 
				
			||||||
 | 
					 *      5 : Input tag1 encrypted buffer descriptor.
 | 
				
			||||||
 | 
					 *      6 : Input tag1 encrypted buffer ptr.
 | 
				
			||||||
 | 
					 *     64 : Output buffer descriptor.
 | 
				
			||||||
 | 
					 *     65 : Output buffer ptr.
 | 
				
			||||||
 | 
					 *  Outputs:
 | 
				
			||||||
 | 
					 *      0 : Return header
 | 
				
			||||||
 | 
					 *      1 : Result of function, 0 on success, otherwise error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void DecryptBeaconData(Interface* self) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 0, 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t desc_size;
 | 
				
			||||||
 | 
					    const VAddr network_struct_addr = rp.PopStaticBuffer(&desc_size);
 | 
				
			||||||
 | 
					    ASSERT(desc_size == sizeof(NetworkInfo));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t data0_size;
 | 
				
			||||||
 | 
					    const VAddr encrypted_data0_addr = rp.PopStaticBuffer(&data0_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t data1_size;
 | 
				
			||||||
 | 
					    const VAddr encrypted_data1_addr = rp.PopStaticBuffer(&data1_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t output_buffer_size;
 | 
				
			||||||
 | 
					    const VAddr output_buffer_addr = rp.PeekStaticBuffer(0, &output_buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This size is hardcoded in the 3DS UDS code.
 | 
				
			||||||
 | 
					    ASSERT(output_buffer_size == sizeof(NodeInfo) * UDSMaxNodes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_WARNING(Service_NWM, "called in0=%08X in1=%08X out=%08X", encrypted_data0_addr,
 | 
				
			||||||
 | 
					                encrypted_data1_addr, output_buffer_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NetworkInfo net_info;
 | 
				
			||||||
 | 
					    Memory::ReadBlock(network_struct_addr, &net_info, sizeof(net_info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Read the encrypted data.
 | 
				
			||||||
 | 
					    // The first 4 bytes should be the OUI and the OUI Type of the tags.
 | 
				
			||||||
 | 
					    std::array<u8, 3> oui;
 | 
				
			||||||
 | 
					    Memory::ReadBlock(encrypted_data0_addr, oui.data(), oui.size());
 | 
				
			||||||
 | 
					    ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
 | 
				
			||||||
 | 
					    Memory::ReadBlock(encrypted_data1_addr, oui.data(), oui.size());
 | 
				
			||||||
 | 
					    ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ASSERT_MSG(Memory::Read8(encrypted_data0_addr + 3) ==
 | 
				
			||||||
 | 
					                   static_cast<u8>(NintendoTagId::EncryptedData0),
 | 
				
			||||||
 | 
					               "Unexpected tag id");
 | 
				
			||||||
 | 
					    ASSERT_MSG(Memory::Read8(encrypted_data1_addr + 3) ==
 | 
				
			||||||
 | 
					                   static_cast<u8>(NintendoTagId::EncryptedData1),
 | 
				
			||||||
 | 
					               "Unexpected tag id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<u8> beacon_data(data0_size + data1_size);
 | 
				
			||||||
 | 
					    Memory::ReadBlock(encrypted_data0_addr + 4, beacon_data.data(), data0_size);
 | 
				
			||||||
 | 
					    Memory::ReadBlock(encrypted_data1_addr + 4, beacon_data.data() + data0_size, data1_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Decrypt the data
 | 
				
			||||||
 | 
					    DecryptBeaconData(net_info, beacon_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The beacon data header contains the MD5 hash of the data.
 | 
				
			||||||
 | 
					    BeaconData beacon_header;
 | 
				
			||||||
 | 
					    std::memcpy(&beacon_header, beacon_data.data(), sizeof(beacon_header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO(Subv): Verify the MD5 hash of the data and return 0xE1211005 if invalid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u8 num_nodes = net_info.max_nodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<NodeInfo> nodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < num_nodes; ++i) {
 | 
				
			||||||
 | 
					        BeaconNodeInfo info;
 | 
				
			||||||
 | 
					        std::memcpy(&info, beacon_data.data() + sizeof(beacon_header) + i * sizeof(info),
 | 
				
			||||||
 | 
					                    sizeof(info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Deserialize the node information.
 | 
				
			||||||
 | 
					        NodeInfo node{};
 | 
				
			||||||
 | 
					        node.friend_code_seed = info.friend_code_seed;
 | 
				
			||||||
 | 
					        node.network_node_id = info.network_node_id;
 | 
				
			||||||
 | 
					        for (int i = 0; i < info.username.size(); ++i)
 | 
				
			||||||
 | 
					            node.username[i] = info.username[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nodes.push_back(node);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Memory::ZeroBlock(output_buffer_addr, sizeof(NodeInfo) * UDSMaxNodes);
 | 
				
			||||||
 | 
					    Memory::WriteBlock(output_buffer_addr, nodes.data(), sizeof(NodeInfo) * nodes.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
 | 
				
			||||||
 | 
					    rb.PushStaticBuffer(output_buffer_addr, output_buffer_size, 0);
 | 
				
			||||||
 | 
					    rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sends a 802.11 beacon frame with information about the current network.
 | 
					// Sends a 802.11 beacon frame with information about the current network.
 | 
				
			||||||
static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
 | 
					static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
 | 
				
			||||||
    // Don't do anything if we're not actually hosting a network
 | 
					    // Don't do anything if we're not actually hosting a network
 | 
				
			||||||
@ -462,7 +558,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
				
			|||||||
    {0x001B0302, InitializeWithVersion, "InitializeWithVersion"},
 | 
					    {0x001B0302, InitializeWithVersion, "InitializeWithVersion"},
 | 
				
			||||||
    {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"},
 | 
					    {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"},
 | 
				
			||||||
    {0x001E0084, nullptr, "ConnectToNetwork"},
 | 
					    {0x001E0084, nullptr, "ConnectToNetwork"},
 | 
				
			||||||
    {0x001F0006, nullptr, "DecryptBeaconData"},
 | 
					    {0x001F0006, DecryptBeaconData, "DecryptBeaconData"},
 | 
				
			||||||
    {0x00200040, nullptr, "Flush"},
 | 
					    {0x00200040, nullptr, "Flush"},
 | 
				
			||||||
    {0x00210080, nullptr, "SetProbeResponseParam"},
 | 
					    {0x00210080, nullptr, "SetProbeResponseParam"},
 | 
				
			||||||
    {0x00220402, nullptr, "ScanOnConnection"},
 | 
					    {0x00220402, nullptr, "ScanOnConnection"},
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user