summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/nwm/nwm_uds.cpp98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
index 581816e81..a82cc9bd3 100644
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ b/src/core/hle/service/nwm/nwm_uds.cpp
@@ -422,6 +422,102 @@ static void SetApplicationData(Interface* self) {
422 rb.Push(RESULT_SUCCESS); 422 rb.Push(RESULT_SUCCESS);
423} 423}
424 424
425/**
426 * NWM_UDS::DecryptBeaconData service function.
427 * Decrypts the encrypted data tags contained in the 802.11 beacons.
428 * Inputs:
429 * 1 : Input network struct buffer descriptor.
430 * 2 : Input network struct buffer ptr.
431 * 3 : Input tag0 encrypted buffer descriptor.
432 * 4 : Input tag0 encrypted buffer ptr.
433 * 5 : Input tag1 encrypted buffer descriptor.
434 * 6 : Input tag1 encrypted buffer ptr.
435 * 64 : Output buffer descriptor.
436 * 65 : Output buffer ptr.
437 * Outputs:
438 * 0 : Return header
439 * 1 : Result of function, 0 on success, otherwise error code
440 */
441static void DecryptBeaconData(Interface* self) {
442 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 0, 6);
443
444 size_t desc_size;
445 const VAddr network_struct_addr = rp.PopStaticBuffer(&desc_size);
446 ASSERT(desc_size == sizeof(NetworkInfo));
447
448 size_t data0_size;
449 const VAddr encrypted_data0_addr = rp.PopStaticBuffer(&data0_size);
450
451 size_t data1_size;
452 const VAddr encrypted_data1_addr = rp.PopStaticBuffer(&data1_size);
453
454 size_t output_buffer_size;
455 const VAddr output_buffer_addr = rp.PeekStaticBuffer(0, &output_buffer_size);
456
457 // This size is hardcoded in the 3DS UDS code.
458 ASSERT(output_buffer_size == sizeof(NodeInfo) * UDSMaxNodes);
459
460 LOG_WARNING(Service_NWM, "called in0=%08X in1=%08X out=%08X", encrypted_data0_addr,
461 encrypted_data1_addr, output_buffer_addr);
462
463 NetworkInfo net_info;
464 Memory::ReadBlock(network_struct_addr, &net_info, sizeof(net_info));
465
466 // Read the encrypted data.
467 // The first 4 bytes should be the OUI and the OUI Type of the tags.
468 std::array<u8, 3> oui;
469 Memory::ReadBlock(encrypted_data0_addr, oui.data(), oui.size());
470 ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
471 Memory::ReadBlock(encrypted_data1_addr, oui.data(), oui.size());
472 ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI");
473
474 ASSERT_MSG(Memory::Read8(encrypted_data0_addr + 3) ==
475 static_cast<u8>(NintendoTagId::EncryptedData0),
476 "Unexpected tag id");
477 ASSERT_MSG(Memory::Read8(encrypted_data1_addr + 3) ==
478 static_cast<u8>(NintendoTagId::EncryptedData1),
479 "Unexpected tag id");
480
481 std::vector<u8> beacon_data(data0_size + data1_size);
482 Memory::ReadBlock(encrypted_data0_addr + 4, beacon_data.data(), data0_size);
483 Memory::ReadBlock(encrypted_data1_addr + 4, beacon_data.data() + data0_size, data1_size);
484
485 // Decrypt the data
486 DecryptBeaconData(net_info, beacon_data);
487
488 // The beacon data header contains the MD5 hash of the data.
489 BeaconData beacon_header;
490 std::memcpy(&beacon_header, beacon_data.data(), sizeof(beacon_header));
491
492 // TODO(Subv): Verify the MD5 hash of the data and return 0xE1211005 if invalid.
493
494 u8 num_nodes = net_info.max_nodes;
495
496 std::vector<NodeInfo> nodes;
497
498 for (int i = 0; i < num_nodes; ++i) {
499 BeaconNodeInfo info;
500 std::memcpy(&info, beacon_data.data() + sizeof(beacon_header) + i * sizeof(info),
501 sizeof(info));
502
503 // Deserialize the node information.
504 NodeInfo node{};
505 node.friend_code_seed = info.friend_code_seed;
506 node.network_node_id = info.network_node_id;
507 for (int i = 0; i < info.username.size(); ++i)
508 node.username[i] = info.username[i];
509
510 nodes.push_back(node);
511 }
512
513 Memory::ZeroBlock(output_buffer_addr, sizeof(NodeInfo) * UDSMaxNodes);
514 Memory::WriteBlock(output_buffer_addr, nodes.data(), sizeof(NodeInfo) * nodes.size());
515
516 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
517 rb.PushStaticBuffer(output_buffer_addr, output_buffer_size, 0);
518 rb.Push(RESULT_SUCCESS);
519}
520
425// Sends a 802.11 beacon frame with information about the current network. 521// Sends a 802.11 beacon frame with information about the current network.
426static void BeaconBroadcastCallback(u64 userdata, int cycles_late) { 522static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
427 // Don't do anything if we're not actually hosting a network 523 // Don't do anything if we're not actually hosting a network
@@ -462,7 +558,7 @@ const Interface::FunctionInfo FunctionTable[] = {
462 {0x001B0302, InitializeWithVersion, "InitializeWithVersion"}, 558 {0x001B0302, InitializeWithVersion, "InitializeWithVersion"},
463 {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"}, 559 {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"},
464 {0x001E0084, nullptr, "ConnectToNetwork"}, 560 {0x001E0084, nullptr, "ConnectToNetwork"},
465 {0x001F0006, nullptr, "DecryptBeaconData"}, 561 {0x001F0006, DecryptBeaconData, "DecryptBeaconData"},
466 {0x00200040, nullptr, "Flush"}, 562 {0x00200040, nullptr, "Flush"},
467 {0x00210080, nullptr, "SetProbeResponseParam"}, 563 {0x00210080, nullptr, "SetProbeResponseParam"},
468 {0x00220402, nullptr, "ScanOnConnection"}, 564 {0x00220402, nullptr, "ScanOnConnection"},