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

Commit fea3f15d authored by Jack He's avatar Jack He Committed by android-build-merger
Browse files

Merge "Metrics: Add Bluetooth address obfuscator"

am: dce81236

Change-Id: I02e0c1a734e55ead434c7e0b3a1696a03eaa027d
parents 7b3cbd16 dce81236
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ cc_library_static {
        "libhidltransport",
        "libhwbinder",
        "libutils",
        "libcrypto",
    ],
    whole_static_libs: [
        "avrcp-target-service",
@@ -130,6 +131,7 @@ cc_test {
        "libprotobuf-cpp-lite",
        "libcutils",
        "libutils",
        "libcrypto",
    ],
    static_libs: [
        "libbt-bta",
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@
#include "btif_storage.h"
#include "btsnoop.h"
#include "btsnoop_mem.h"
#include "common/address_obfuscator.h"
#include "common/metrics.h"
#include "device/include/interop.h"
#include "osi/include/alarm.h"
@@ -453,6 +454,11 @@ static bluetooth::avrcp::ServiceInterface* get_avrcp_service(void) {
  return bluetooth::avrcp::AvrcpService::GetServiceInterface();
}

static std::string obfuscate_address(const RawAddress& address) {
  return bluetooth::common::AddressObfuscator::GetInstance()->Obfuscate(
      address);
}

EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
    sizeof(bluetoothInterface),
    init,
@@ -488,4 +494,5 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
    interop_database_clear,
    interop_database_add,
    get_avrcp_service,
    obfuscate_address,
};
+73 −20
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <base/logging.h>
#include <ctype.h>
#include <openssl/rand.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -36,6 +37,7 @@
#include "btif_common.h"
#include "btif_config_transcode.h"
#include "btif_util.h"
#include "common/address_obfuscator.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
@@ -52,6 +54,10 @@
#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";

#define BT_CONFIG_METRICS_SECTION "Metrics"
#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
using bluetooth::common::AddressObfuscator;

// TODO(armansito): Find a better way than searching by a hardcoded path.
#if defined(OS_GENERIC)
static const char* CONFIG_FILE_PATH = "bt_config.conf";
@@ -114,14 +120,48 @@ bool btif_get_address_type(const RawAddress& bda, int* p_addr_type) {
  return true;
}

static std::mutex config_lock;  // protects operations on |config|.
/**
 * Read metrics salt from config file, if salt is invalid or does not exist,
 * generate new one and save it to config
 */
static void read_or_set_metrics_salt() {
  AddressObfuscator::Octet32 metrics_salt = {};
  size_t metrics_salt_length = metrics_salt.size();
  if (!btif_config_get_bin(BT_CONFIG_METRICS_SECTION,
                           BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
                           &metrics_salt_length)) {
    LOG(WARNING) << __func__ << ": Failed to read metrics salt from config";
    // Invalidate salt
    metrics_salt.fill(0);
  }
  if (metrics_salt_length != metrics_salt.size()) {
    LOG(ERROR) << __func__ << ": Metrics salt length incorrect, "
               << metrics_salt_length << " instead of " << metrics_salt.size();
    // Invalidate salt
    metrics_salt.fill(0);
  }
  if (!AddressObfuscator::IsSaltValid(metrics_salt)) {
    LOG(INFO) << __func__ << ": Metrics salt is] not invalid, creating new one";
    if (RAND_bytes(metrics_salt.data(), metrics_salt.size()) != 1) {
      LOG(FATAL) << __func__ << "Failed to generate salt for metrics";
    }
    if (!btif_config_set_bin(BT_CONFIG_METRICS_SECTION,
                             BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
                             metrics_salt.size())) {
      LOG(FATAL) << __func__ << "Failed to write metrics salt to config";
    }
  }
  AddressObfuscator::GetInstance()->Initialize(metrics_salt);
}

static std::recursive_mutex config_lock;  // protects operations on |config|.
static std::unique_ptr<config_t> config;
static alarm_t* config_timer;

// Module lifecycle functions

static future_t* init(void) {
  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);

  if (is_factory_reset()) delete_config_files();

@@ -175,6 +215,9 @@ static future_t* init(void) {
                      btif_config_time_created);
  }

  // Read or set metrics 256 bit hashing salt
  read_or_set_metrics_salt();

  // TODO(sharvil): use a non-wake alarm for this once we have
  // API support for it. There's no need to wake the system to
  // write back to disk.
@@ -219,7 +262,7 @@ static future_t* clean_up(void) {
  alarm_free(config_timer);
  config_timer = NULL;

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  config.reset();
  return future_new_immediate(FUTURE_SUCCESS);
}
@@ -234,14 +277,14 @@ bool btif_config_has_section(const char* section) {
  CHECK(config != NULL);
  CHECK(section != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  return config_has_section(*config, section);
}

bool btif_config_exist(const std::string& section, const std::string& key) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  return config_has_key(*config, section, key);
}

@@ -250,7 +293,7 @@ bool btif_config_get_int(const std::string& section, const std::string& key,
  CHECK(config != NULL);
  CHECK(value != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  bool ret = config_has_key(*config, section, key);
  if (ret) *value = config_get_int(*config, section, key, *value);

@@ -261,7 +304,7 @@ bool btif_config_set_int(const std::string& section, const std::string& key,
                         int value) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  config_set_int(config.get(), section, key, value);

  return true;
@@ -272,7 +315,7 @@ bool btif_config_get_uint64(const std::string& section, const std::string& key,
  CHECK(config != NULL);
  CHECK(value != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  bool ret = config_has_key(*config, section, key);
  if (ret) *value = config_get_uint64(*config, section, key, *value);

@@ -283,7 +326,7 @@ bool btif_config_set_uint64(const std::string& section, const std::string& key,
                            uint64_t value) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  config_set_uint64(config.get(), section, key, value);

  return true;
@@ -296,7 +339,7 @@ bool btif_config_get_str(const std::string& section, const std::string& key,
  CHECK(size_bytes != NULL);

  {
    std::unique_lock<std::mutex> lock(config_lock);
    std::unique_lock<std::recursive_mutex> lock(config_lock);
    const std::string* stored_value =
        config_get_string(*config, section, key, NULL);
    if (!stored_value) return false;
@@ -311,7 +354,7 @@ bool btif_config_set_str(const std::string& section, const std::string& key,
                         const std::string& value) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  config_set_string(config.get(), section, key, value);
  return true;
}
@@ -322,16 +365,26 @@ bool btif_config_get_bin(const std::string& section, const std::string& key,
  CHECK(value != NULL);
  CHECK(length != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  const std::string* value_str = config_get_string(*config, section, key, NULL);

  if (!value_str) return false;
  if (!value_str) {
    LOG(WARNING) << __func__ << ": cannot find string for section " << section
                 << ", key " << key;
    return false;
  }

  size_t value_len = value_str->length();
  if ((value_len % 2) != 0 || *length < (value_len / 2)) return false;
  if ((value_len % 2) != 0 || *length < (value_len / 2)) {
    LOG(WARNING) << ": value size not divisible by 2, size is " << value_len;
    return false;
  }

  for (size_t i = 0; i < value_len; ++i)
    if (!isxdigit(value_str->c_str()[i])) return false;
    if (!isxdigit(value_str->c_str()[i])) {
      LOG(WARNING) << ": value is not hex digit";
      return false;
    }

  const char* ptr = value_str->c_str();
  for (*length = 0; *ptr; ptr += 2, *length += 1)
@@ -344,7 +397,7 @@ size_t btif_config_get_bin_length(const std::string& section,
                                  const std::string& key) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  const std::string* value_str = config_get_string(*config, section, key, NULL);
  if (!value_str) return 0;

@@ -368,7 +421,7 @@ bool btif_config_set_bin(const std::string& section, const std::string& key,
  }

  {
    std::unique_lock<std::mutex> lock(config_lock);
    std::unique_lock<std::recursive_mutex> lock(config_lock);
    config_set_string(config.get(), section, key, str);
  }

@@ -381,7 +434,7 @@ std::list<section_t>& btif_config_sections() { return config->sections; }
bool btif_config_remove(const std::string& section, const std::string& key) {
  CHECK(config != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  return config_remove_key(config.get(), section, key);
}

@@ -406,7 +459,7 @@ bool btif_config_clear(void) {

  alarm_cancel(config_timer);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);

  config = config_new_empty();

@@ -427,7 +480,7 @@ static void btif_config_write(UNUSED_ATTR uint16_t event,
  CHECK(config != NULL);
  CHECK(config_timer != NULL);

  std::unique_lock<std::mutex> lock(config_lock);
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
  std::unique_ptr<config_t> config_paired = config_new_clone(*config);
  btif_config_remove_unpaired(config_paired.get());
+6 −0
Original line number Diff line number Diff line
@@ -7,11 +7,15 @@ cc_library_static {
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs: [
        "address_obfuscator.cc",
        "timer.cc",
        "message_loop_thread.cc",
        "metrics.cc",
        "time_util.cc",
    ],
    shared_libs: [
        "libcrypto",
    ],
    static_libs: [
        "libbt-protos-lite",
    ],
@@ -27,6 +31,7 @@ cc_test {
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs : [
        "address_obfuscator_unittest.cc",
        "timer_unittest.cc",
        "leaky_bonded_queue_unittest.cc",
        "message_loop_thread_unittest.cc",
@@ -36,6 +41,7 @@ cc_test {
    ],
    shared_libs: [
        "libprotobuf-cpp-lite",
        "libcrypto",
    ],
    static_libs : [
        "libgmock",
+59 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2018 Google, Inc.
 *
 *  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 "address_obfuscator.h"

#include <algorithm>

#include <base/logging.h>
#include <openssl/hmac.h>

#include "bt_trace.h"

namespace bluetooth {
namespace common {

bool AddressObfuscator::IsSaltValid(const Octet32& salt_256bit) {
  return !std::all_of(salt_256bit.begin(), salt_256bit.end(),
                      [](uint8_t i) { return i == 0; });
}

void AddressObfuscator::Initialize(const Octet32& salt_256bit) {
  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
  salt_256bit_ = salt_256bit;
}

bool AddressObfuscator::IsInitialized() {
  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
  return IsSaltValid(salt_256bit_);
}

std::string AddressObfuscator::Obfuscate(const RawAddress& address) {
  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
  CHECK(IsInitialized());
  std::array<uint8_t, EVP_MAX_MD_SIZE> result = {};
  unsigned int out_len = 0;
  CHECK(::HMAC(EVP_sha256(), salt_256bit_.data(), salt_256bit_.size(),
               address.address, address.kLength, result.data(),
               &out_len) != nullptr);
  CHECK_EQ(out_len, static_cast<unsigned int>(kOctet32Length));
  return std::string(reinterpret_cast<const char*>(result.data()), out_len);
}

}  // namespace common
}  // namespace bluetooth
 No newline at end of file
Loading