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

Commit e29e0f18 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

LE Pairing Handler

Bug: 139138713
Test: unit tests added in CL
Change-Id: I73c0db6bea87257e299ed97bb6fc202234221d5f
parent 04933b7a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -310,10 +310,12 @@ genrule {
    srcs: [
        "hci/hci_packets.pdl",
        "l2cap/l2cap_packets.pdl",
        "smp/smp_packets.pdl",
    ],
    out: [
        "hci/hci_packets.h",
        "l2cap/l2cap_packets.h",
        "smp/smp_packets.h",
    ],
}

+97 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 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.
 *
 ******************************************************************************/

#pragma once

#include <memory>

#include "common/bidi_queue.h"
#include "os/handler.h"
#include "packet/base_packet_builder.h"
#include "packet/bit_inserter.h"
#include "packet/packet_view.h"

namespace bluetooth {
namespace common {
namespace testing {

/* This class is a pair of BiDiQueues, that have down ends "wired" together. It can be used i.e. to mock L2cap
 * interface, and provide two queues, where each sends packets of type A, and receives packets of type B */
template <class A, class B, std::unique_ptr<B> (*A_TO_B)(std::unique_ptr<A>)>
class WiredPairOfBiDiQueues {
  void dequeue_callback_a() {
    auto down_thing = queue_a_.GetDownEnd()->TryDequeue();
    if (!down_thing) LOG_ERROR("Received dequeue, but no data ready...");

    down_buffer_b_.Enqueue(A_TO_B(std::move(down_thing)), handler_);
  }

  void dequeue_callback_b() {
    auto down_thing = queue_b_.GetDownEnd()->TryDequeue();
    if (!down_thing) LOG_ERROR("Received dequeue, but no data ready...");

    down_buffer_a_.Enqueue(A_TO_B(std::move(down_thing)), handler_);
  }

  os::Handler* handler_;
  common::BidiQueue<B, A> queue_a_{10};
  common::BidiQueue<B, A> queue_b_{10};
  os::EnqueueBuffer<B> down_buffer_a_{queue_a_.GetDownEnd()};
  os::EnqueueBuffer<B> down_buffer_b_{queue_b_.GetDownEnd()};

 public:
  WiredPairOfBiDiQueues(os::Handler* handler) : handler_(handler) {
    queue_a_.GetDownEnd()->RegisterDequeue(
        handler_, common::Bind(&WiredPairOfBiDiQueues::dequeue_callback_a, common::Unretained(this)));
    queue_b_.GetDownEnd()->RegisterDequeue(
        handler_, common::Bind(&WiredPairOfBiDiQueues::dequeue_callback_b, common::Unretained(this)));
  }

  ~WiredPairOfBiDiQueues() {
    queue_a_.GetDownEnd()->UnregisterDequeue();
    queue_b_.GetDownEnd()->UnregisterDequeue();
  }

  /* This methd returns the UpEnd of queue A */
  common::BidiQueueEnd<A, B>* GetQueueAUpEnd() {
    return queue_a_.GetUpEnd();
  }

  /* This methd returns the UpEnd of queue B */
  common::BidiQueueEnd<A, B>* GetQueueBUpEnd() {
    return queue_b_.GetUpEnd();
  }
};

namespace {
std::unique_ptr<packet::PacketView<packet::kLittleEndian>> BuilderToView(
    std::unique_ptr<packet::BasePacketBuilder> up_thing) {
  auto bytes = std::make_shared<std::vector<uint8_t>>();
  bluetooth::packet::BitInserter i(*bytes);
  bytes->reserve(up_thing->size());
  up_thing->Serialize(i);
  return std::make_unique<packet::PacketView<packet::kLittleEndian>>(bytes);
}
}  // namespace

using WiredPairOfL2capQueues =
    WiredPairOfBiDiQueues<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>, BuilderToView>;

}  // namespace testing
}  // namespace common
}  // namespace bluetooth
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "common/callback.h"
#include "hci/hci_packets.h"
#include "os/handler.h"
#include "os/utils.h"

namespace bluetooth {
+7 −0
Original line number Diff line number Diff line
@@ -3,6 +3,10 @@ filegroup {
    srcs: [
        "ecc/multprecision.cc",
        "ecc/p_256_ecc_pp.cc",
        "ecdh_keys.cc",
        "pairing_handler_le.cc",
        "pairing_handler_le_legacy.cc",
        "pairing_handler_le_secure_connections.cc",
    ]
}

@@ -10,5 +14,8 @@ filegroup {
    name: "BluetoothSmpTestSources",
    srcs: [
        "ecc/multipoint_test.cc",
        "pairing_handler_le_unittest.cc",
        "test/fake_l2cap_test.cc",
        "test/pairing_handler_le_pair_test.cc",
    ]
}
 No newline at end of file
+82 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 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 "smp/ecdh_keys.h"

/**********************************************************************************************************************
 TODO: We should have random number management in separate file, and we
       should honour all the random number requirements from the spec!!
**********************************************************************************************************************/
#include <chrono>
#include <cstdlib>

#include "smp/ecc/p_256_ecc_pp.h"

namespace {
template <size_t SIZE>
static std::array<uint8_t, SIZE> GenerateRandom() {
  // TODO:  We need a proper  random number generator here.
  // use current time as seed for random generator
  std::srand(std::time(nullptr));
  std::array<uint8_t, SIZE> r;
  for (size_t i = 0; i < SIZE; i++) r[i] = std::rand();
  return r;
}
}  // namespace
/*********************************************************************************************************************/

namespace bluetooth {
namespace smp {

std::pair<std::array<uint8_t, 32>, EcdhPublicKey> GenerateECDHKeyPair() {
  std::array<uint8_t, 32> private_key = GenerateRandom<32>();
  ecc::Point public_key;

  ECC_PointMult(&public_key, &(ecc::curve_p256.G), (uint32_t*)private_key.data());

  EcdhPublicKey pk;
  memcpy(pk.x.data(), public_key.x, 32);
  memcpy(pk.y.data(), public_key.y, 32);

  /* private_key, public key pair */
  return std::make_pair<std::array<uint8_t, 32>, EcdhPublicKey>(std::move(private_key), std::move(pk));
}

bool ValidateECDHPoint(EcdhPublicKey pk) {
  ecc::Point public_key;
  memcpy(public_key.x, pk.x.data(), 32);
  memcpy(public_key.y, pk.y.data(), 32);
  memset(public_key.z, 0, 32);
  return ECC_ValidatePoint(public_key);
}

std::array<uint8_t, 32> ComputeDHKey(std::array<uint8_t, 32> my_private_key, EcdhPublicKey remote_public_key) {
  ecc::Point peer_publ_key, new_publ_key;
  uint32_t private_key[8];
  memcpy(private_key, my_private_key.data(), 32);
  memcpy(peer_publ_key.x, remote_public_key.x.data(), 32);
  memcpy(peer_publ_key.y, remote_public_key.y.data(), 32);
  ECC_PointMult(&new_publ_key, &peer_publ_key, (uint32_t*)private_key);

  std::array<uint8_t, 32> dhkey;
  memcpy(dhkey.data(), new_publ_key.x, 32);
  return dhkey;
}

}  // namespace smp
}  // namespace bluetooth
Loading