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

Commit 3adeb3ba authored by Martin Brabham's avatar Martin Brabham
Browse files

Security: New API; GetOutOfBandData

Add a new API to the SecurityManager.  This API
will allow for a caller to fetch OOB data from the
controller.

Bug: 162984360
Tag: #gd-refactor
Test: cert/run --host SecurityTest:test_get_oob_data_from_dut_controller_p192_present
Change-Id: Icb204c110345c9113049a4b1e57aae56845e9f51
parent b059d4b0
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ class PySecurity(Closable):

    _ui_event_stream = None
    _bond_event_stream = None
    _oob_data_event_stream = None

    def __init__(self, device):
        logging.debug("DUT: Init")
@@ -72,6 +73,8 @@ class PySecurity(Closable):
        self._enforce_security_policy_stream = EventStream(
            self._device.security.FetchEnforceSecurityPolicyEvents(empty_proto.Empty()))
        self._disconnect_event_stream = EventStream(self._device.security.FetchDisconnectEvents(empty_proto.Empty()))
        self._oob_data_event_stream = EventStream(
            self._device.security.FetchGetOutOfBandDataEvents(empty_proto.Empty()))

    def create_bond(self, address, type):
        """
@@ -253,8 +256,24 @@ class PySecurity(Closable):
                address=common.BluetoothAddressWithType(address=common.BluetoothAddress(address=address), type=type),
                policy=policy))

    def get_oob_data_from_controller(self, oob_data_present):
        self._device.security.GetOutOfBandData(empty_proto.Empty())
        oob_data = []

        def get_oob_data(event):
            nonlocal oob_data
            oob_data = [
                list(event.p192_data.confirmation_value),
                list(event.p192_data.random_value), [0 for i in range(0, 16)], [0 for i in range(0, 16)]
            ]
            return True

        assertThat(self._oob_data_event_stream).emits(get_oob_data)
        return oob_data

    def close(self):
        safeClose(self._ui_event_stream)
        safeClose(self._bond_event_stream)
        safeClose(self._enforce_security_policy_stream)
        safeClose(self._disconnect_event_stream)
        safeClose(self._oob_data_event_stream)
+17 −5
Original line number Diff line number Diff line
@@ -357,7 +357,19 @@ class SecurityTest(GdBaseTestClass):
        self.dut_security.enable_secure_connections()
        self.cert_security.enable_secure_connections()

    def test_get_oob_data_from_controller_not_present(self):
    def test_get_oob_data_from_dut_controller_p192_present(self):
        oob_data = self.dut_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
        assertThat(len(oob_data)).isEqualTo(4)
        has192C = not all([i == 0 for i in oob_data[0]])
        has192R = not all([i == 0 for i in oob_data[1]])
        has256C = not all([i == 0 for i in oob_data[2]])
        has256R = not all([i == 0 for i in oob_data[3]])
        assertThat(has192C).isTrue()
        assertThat(has192R).isTrue()
        assertThat(has256C).isFalse()
        assertThat(has256R).isFalse()

    def test_get_oob_data_from_cert_controller_not_present(self):
        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.NOT_PRESENT)
        assertThat(len(oob_data)).isEqualTo(4)
        has192C = not all([i == 0 for i in oob_data[0]])
@@ -369,7 +381,7 @@ class SecurityTest(GdBaseTestClass):
        assertThat(has256C).isFalse()
        assertThat(has256R).isFalse()

    def test_get_oob_data_from_controller_p192_present_no_secure_connections(self):
    def test_get_oob_data_from_cert_controller_p192_present_no_secure_connections(self):
        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
        assertThat(len(oob_data)).isEqualTo(4)
        has192C = not all([i == 0 for i in oob_data[0]])
@@ -381,7 +393,7 @@ class SecurityTest(GdBaseTestClass):
        assertThat(has256C).isFalse()
        assertThat(has256R).isFalse()

    def test_get_oob_data_from_controller_p192_present(self):
    def test_get_oob_data_from_cert_controller_p192_present(self):
        self.cert_security.enable_secure_simple_pairing()
        self.cert_security.enable_secure_connections()
        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
@@ -395,7 +407,7 @@ class SecurityTest(GdBaseTestClass):
        assertThat(has256C).isFalse()
        assertThat(has256R).isFalse()

    def test_get_oob_data_from_controller_p256_present(self):
    def test_get_oob_data_from_cert_controller_p256_present(self):
        self.cert_security.enable_secure_simple_pairing()
        self.cert_security.enable_secure_connections()
        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P256_PRESENT)
@@ -409,7 +421,7 @@ class SecurityTest(GdBaseTestClass):
        assertThat(has256C).isTrue()
        assertThat(has256R).isTrue()

    def test_get_oob_data_from_controller_p192_and_p256_present(self):
    def test_get_oob_data_from_cert_controller_p192_and_p256_present(self):
        self.cert_security.enable_secure_simple_pairing()
        self.cert_security.enable_secure_connections()
        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_AND_256_PRESENT)
+5 −0
Original line number Diff line number Diff line
@@ -80,6 +80,11 @@ void SecurityManagerChannel::SendCommand(std::unique_ptr<hci::SecurityCommandBui
                                          handler_->BindOnceOn(this, &SecurityManagerChannel::OnCommandComplete));
}

void SecurityManagerChannel::SendCommand(
    std::unique_ptr<hci::SecurityCommandBuilder> command, SecurityCommandStatusCallback callback) {
  hci_security_interface_->EnqueueCommand(std::move(command), std::forward<SecurityCommandStatusCallback>(callback));
}

void SecurityManagerChannel::OnHciEventReceived(hci::EventPacketView packet) {
  ASSERT_LOG(listener_ != nullptr, "No listener set!");
  ASSERT(packet.IsValid());
+11 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <unordered_map>
#include <vector>

#include "common/contextual_callback.h"
#include "hci/address_with_type.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
@@ -32,6 +33,8 @@ namespace bluetooth {
namespace security {
namespace channel {

using SecurityCommandStatusCallback = common::ContextualOnceCallback<void(hci::CommandCompleteView)>;

/**
 * Interface for listening to the channel for SMP commands.
 */
@@ -83,6 +86,14 @@ class SecurityManagerChannel : public l2cap::classic::LinkSecurityInterfaceListe
   */
  void SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command);

  /**
   * Send a given SMP command over the SecurityManagerChannel
   *
   * @param command smp command to send
   * @param callback listener to call when command status complete
   */
  void SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command, SecurityCommandStatusCallback callback);

  /**
   * Sets the listener to listen for channel events
   *
+50 −0
Original line number Diff line number Diff line
@@ -125,6 +125,22 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public
    return ::grpc::Status::OK;
  }

  ::grpc::Status GetOutOfBandData(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::google::protobuf::Empty* response) override {
    security_module_->GetSecurityManager()->GetOutOfBandData(
        security_handler_->BindOnceOn(this, &SecurityModuleFacadeService::OobDataEventOccurred));
    return ::grpc::Status::OK;
  }

  ::grpc::Status FetchGetOutOfBandDataEvents(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::grpc::ServerWriter<OobDataBondMessage>* writer) override {
    return oob_events_.RunLoop(context, writer);
  }

  ::grpc::Status CreateBondLe(::grpc::ServerContext* context, const facade::BluetoothAddressWithType* request,
                              ::google::protobuf::Empty* response) override {
    hci::Address peer;
@@ -356,6 +372,39 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public
    return disconnect_events_.RunLoop(context, writer);
  }

  void OobDataEventOccurred(bluetooth::hci::CommandCompleteView packet) {
    LOG_INFO("Got OOB Data event");
    ASSERT(packet.IsValid());
    auto cc = bluetooth::hci::ReadLocalOobDataCompleteView::Create(packet);
    ASSERT(cc.IsValid());
    OobDataBondMessage msg;
    OobDataMessage p192;
    // Just need this to satisfy the proto message
    bluetooth::hci::AddressWithType peer;
    *p192.mutable_address() = ToFacadeAddressWithType(peer);

    auto c = cc.GetC();
    p192.set_confirmation_value(c.data(), c.size());

    auto r = cc.GetR();
    p192.set_random_value(r.data(), r.size());

    // Only the Extended version returns 256 also.
    // The API has a parameter for both, so we set it
    // empty and the module and test suite will ignore it.
    OobDataMessage p256;
    *p256.mutable_address() = ToFacadeAddressWithType(peer);

    std::array<uint8_t, 16> empty_val;
    p256.set_confirmation_value(empty_val.data(), empty_val.size());
    p256.set_random_value(empty_val.data(), empty_val.size());

    *msg.mutable_address() = ToFacadeAddressWithType(peer);
    *msg.mutable_p192_data() = p192;
    *msg.mutable_p256_data() = p256;
    oob_events_.OnIncomingEvent(msg);
  }

  void DisconnectEventOccurred(bluetooth::hci::AddressWithType peer) {
    LOG_INFO("%s", peer.ToString().c_str());
    DisconnectMsg msg;
@@ -483,6 +532,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public
  ::bluetooth::grpc::GrpcEventQueue<EnforceSecurityPolicyMsg> enforce_security_policy_events_{
      "Enforce Security Policy Events"};
  ::bluetooth::grpc::GrpcEventQueue<DisconnectMsg> disconnect_events_{"Disconnect events"};
  ::bluetooth::grpc::GrpcEventQueue<OobDataBondMessage> oob_events_{"OOB Data events"};
  uint32_t unique_id{1};
  std::map<uint32_t, common::OnceCallback<void(bool)>> user_yes_no_callbacks_;
  std::map<uint32_t, common::OnceCallback<void(uint32_t)>> user_passkey_callbacks_;
Loading