Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccbb9a73 authored by David Duarte's avatar David Duarte
Browse files

RootCanal: Add a Baseband sniffer

This sniffer creates Bluetooth Baseband packet
capture.
Even if RootCanal doesn't use the packet format
of the Bluetooth Baseband a tool that can understand it
(e.g. Wireshark) will be able to decode the upper protocols
like LMP or L2CAP and above.

So this effectively add a LMP sniffer.

Test: manual
Fix: 235777451
Change-Id: I033f30c141e4257f201a6b10b923780cd6d52c79
parent 484ff2af
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ cc_defaults {
    ],
    generated_headers: [
        "RootCanalGeneratedPackets_h",
        "RootCanalBrEdrBBGeneratedPackets_h",
        "BluetoothGeneratedPackets_h",
        "libbt_init_flags_bridge_header",
    ],
@@ -57,6 +58,7 @@ cc_library_static {
        "model/controller/link_layer_controller.cc",
        "model/controller/sco_connection.cc",
        "model/controller/security_manager.cc",
        "model/devices/baseband_sniffer.cc",
        "model/devices/beacon.cc",
        "model/devices/beacon_swarm.cc",
        "model/devices/broken_adv.cc",
@@ -228,6 +230,20 @@ filegroup {
    ],
}

genrule {
    name: "RootCanalBrEdrBBGeneratedPackets_h",
    tools: [
        "bluetooth_packetgen",
    ],
    cmd: "$(location bluetooth_packetgen) --root_namespace=bredr_bb --include=packages/modules/Bluetooth/tools/rootcanal/packets --out=$(genDir) $(in)",
    srcs: [
        "packets/bredr_bb.pdl",
    ],
    out: [
        "bredr_bb.h",
    ],
}

// bt_vhci_forwarder in cuttlefish depends on this H4Packetizer implementation.
cc_library_static {
    name: "h4_packetizer_lib",
+2 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ DEFINE_string(controller_properties_file, "",
DEFINE_string(default_commands_file, "",
              "commands file which root-canal runs it as default");
DEFINE_bool(enable_hci_sniffer, false, "enable hci sniffer");
DEFINE_bool(enable_baseband_sniffer, false, "enable baseband sniffer");

constexpr uint16_t kTestPort = 6401;
constexpr uint16_t kHciServerPort = 6402;
@@ -123,7 +124,7 @@ int main(int argc, char** argv) {
      std::make_shared<PosixAsyncSocketServer>(link_ble_server_port, &am),
      std::make_shared<PosixAsyncSocketConnector>(&am),
      FLAGS_controller_properties_file, FLAGS_default_commands_file,
      FLAGS_enable_hci_sniffer);
      FLAGS_enable_hci_sniffer, FLAGS_enable_baseband_sniffer);
  std::promise<void> barrier;
  std::future<void> barrier_future = barrier.get_future();
  root_canal.initialize(std::move(barrier));
+12 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <utility>      // for move
#include <vector>       // for vector

#include "model/devices/baseband_sniffer.h"
#include "model/devices/link_layer_socket_device.h"  // for LinkLayerSocketDevice
#include "model/hci/hci_sniffer.h"                   // for HciSniffer
#include "model/hci/hci_socket_transport.h"          // for HciSocketTransport
@@ -33,6 +34,7 @@ namespace bluetooth {
namespace root_canal {

using rootcanal::AsyncTaskId;
using rootcanal::BaseBandSniffer;
using rootcanal::HciDevice;
using rootcanal::HciSniffer;
using rootcanal::HciSocketTransport;
@@ -81,6 +83,16 @@ void TestEnvironment::initialize(std::promise<void> barrier) {
  SetUpLinkLayerServer();
  SetUpLinkBleLayerServer();

  if (enable_baseband_sniffer_) {
    std::string filename = "baseband.pcap";
    for (auto i = 0; std::filesystem::exists(filename); i++) {
      filename = "baseband_" + std::to_string(i) + ".pcap";
    }

    test_model_.AddLinkLayerConnection(BaseBandSniffer::Create(filename),
                                       Phy::Type::BR_EDR);
  }

  LOG_INFO("%s: Finished", __func__);
}

+4 −1
Original line number Diff line number Diff line
@@ -55,7 +55,8 @@ class TestEnvironment {
                  std::shared_ptr<AsyncDataChannelConnector> connector,
                  const std::string& controller_properties_file = "",
                  const std::string& default_commands_file = "",
                  bool enable_hci_sniffer = false)
                  bool enable_hci_sniffer = false,
                  bool enable_baseband_sniffer = false)
      : test_socket_server_(test_port),
        hci_socket_server_(hci_server_port),
        link_socket_server_(link_server_port),
@@ -64,6 +65,7 @@ class TestEnvironment {
        controller_properties_file_(controller_properties_file),
        default_commands_file_(default_commands_file),
        enable_hci_sniffer_(enable_hci_sniffer),
        enable_baseband_sniffer_(enable_baseband_sniffer),
        controller_(std::make_shared<rootcanal::DualModeController>(
            controller_properties_file)) {}

@@ -81,6 +83,7 @@ class TestEnvironment {
  std::string controller_properties_file_;
  std::string default_commands_file_;
  bool enable_hci_sniffer_;
  bool enable_baseband_sniffer_;
  bool test_channel_open_{false};
  std::promise<void> barrier_;

+173 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "baseband_sniffer.h"

#include "os/log.h"
#include "packet/raw_builder.h"
#include "pcap.h"

using std::vector;

namespace rootcanal {

#include "bredr_bb.h"

BaseBandSniffer::BaseBandSniffer(const std::string& filename) {
  output_.open(filename, std::ios::binary);

  uint32_t linktype = 255;  // http://www.tcpdump.org/linktypes.html
                            // LINKTYPE_BLUETOOTH_BREDR_BB

  pcap::WriteHeader(output_, linktype);
  output_.flush();
}

void BaseBandSniffer::TimerTick() {}

void BaseBandSniffer::AppendRecord(
    std::unique_ptr<bredr_bb::BaseBandPacketBuilder> packet) {
  auto bytes = std::vector<uint8_t>();
  bytes.reserve(packet->size());
  bluetooth::packet::BitInserter i(bytes);
  packet->Serialize(i);

  pcap::WriteRecordHeader(output_, bytes.size());
  output_.write((char*)bytes.data(), bytes.size());
  output_.flush();
}

static uint8_t ReverseByte(uint8_t b) {
  static uint8_t lookup[16] = {
      [0b0000] = 0b0000, [0b0001] = 0b1000, [0b0010] = 0b0100,
      [0b0011] = 0b1100, [0b0100] = 0b0010, [0b0101] = 0b1010,
      [0b0110] = 0b0110, [0b0111] = 0b1110, [0b1000] = 0b0001,
      [0b1001] = 0b1001, [0b1010] = 0b0101, [0b1011] = 0b1101,
      [0b1100] = 0b0011, [0b1101] = 0b1011, [0b1110] = 0b0111,
      [0b1111] = 0b1111,
  };

  return (lookup[b & 0xF] << 4) | lookup[b >> 4];
}

static uint8_t HeaderErrorCheck(uint8_t uap, uint32_t data) {
  // See Bluetooth Core, Vol 2, Part B, 7.1.1

  uint8_t value = ReverseByte(uap);

  for (auto i = 0; i < 10; i++) {
    bool bit = (value ^ data) & 1;
    data >>= 1;
    value >>= 1;
    if (bit) value ^= 0xe5;
  }

  return value;
}

static uint32_t BuildBtPacketHeader(uint8_t uap, uint8_t lt_addr,
                                    uint8_t packet_type, bool flow, bool arqn,
                                    bool seqn) {
  // See Bluetooth Core, Vol2, Part B, 6.4

  uint32_t header = (lt_addr & 0x7) | ((packet_type & 0xF) << 3) | (flow << 7) |
                    (arqn << 8) | (seqn << 9);

  header |= (HeaderErrorCheck(uap, header) << 10);

  return header;
}

void BaseBandSniffer::IncomingPacket(
    model::packets::LinkLayerPacketView packet) {
  auto packet_type = packet.GetType();
  auto address = packet.GetSourceAddress();

  // Bluetooth Core, Vol2, Part B, 1.2, Figure 1.5
  uint32_t lap =
      address.data()[0] | (address.data()[1] << 8) | (address.data()[2] << 16);
  uint8_t uap = address.data()[3];
  uint16_t nap = address.data()[4] | (address.data()[5] << 8);

  // http://www.whiterocker.com/bt/LINKTYPE_BLUETOOTH_BREDR_BB.html
  uint16_t flags =
      /* BT Packet Header and BR or EDR Payload are de-whitened */ 0x0001 |
      /* BR or EDR Payload is decrypted */ 0x0008 |
      /* Reference LAP is valid and led to this packet being captured */
      0x0010 |
      /* BR or EDR Payload is present and follows this field */ 0x0020 |
      /* Reference UAP field is valid for HEC and CRC checking */ 0x0080 |
      /* CRC portion of the BR or EDR Payload was checked */ 0x0400 |
      /* CRC portion of the BR or EDR Payload passed its check */ 0x0800;

  uint8_t lt_addr = 0;

  uint8_t rf_channel = 0;
  uint8_t signal_power = 0;
  uint8_t noise_power = 0;
  uint8_t access_code_offenses = 0;
  uint8_t corrected_header_bits = 0;
  uint16_t corrected_payload_bits = 0;
  uint8_t lower_address_part = lap;
  uint8_t reference_lap = lap;
  uint8_t reference_uap = uap;

  if (packet_type == model::packets::PacketType::PAGE) {
    auto page_view = model::packets::PageView::Create(packet);
    ASSERT(page_view.IsValid());

    uint8_t bt_packet_type = 0b0010;  // FHS

    AppendRecord(bredr_bb::FHSAclPacketBuilder::Create(
        rf_channel, signal_power, noise_power, access_code_offenses,
        corrected_header_bits, corrected_payload_bits, lower_address_part,
        reference_lap, reference_uap,
        BuildBtPacketHeader(uap, lt_addr, bt_packet_type, true, true, true),
        flags,
        0,  // parity_bits
        lap,
        0,  // eir
        0,  // sr
        0,  // sp
        uap, nap, page_view.GetClassOfDevice().ToUint32Legacy(),
        1,  // lt_addr
        0,  // clk
        0,  // page_scan_mode
        0   // crc
        ));
  } else if (packet_type == model::packets::PacketType::LMP) {
    auto lmp_view = model::packets::LmpView::Create(packet);
    ASSERT(lmp_view.IsValid());
    auto lmp_bytes = std::vector<uint8_t>(lmp_view.GetPayload().begin(),
                                          lmp_view.GetPayload().end());

    uint8_t bt_packet_type = 0b0011;  // DM1

    AppendRecord(bredr_bb::DM1AclPacketBuilder::Create(
        rf_channel, signal_power, noise_power, access_code_offenses,
        corrected_header_bits, corrected_payload_bits, lower_address_part,
        reference_lap, reference_uap,
        BuildBtPacketHeader(uap, lt_addr, bt_packet_type, true, true, true),
        flags,
        0x3,  // llid
        1,    // flow
        std::make_unique<bluetooth::packet::RawBuilder>(lmp_bytes),
        0  // crc
        ));
  }
}

}  // namespace rootcanal
Loading