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

Commit f7d026fc authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "NIAP for AOSP"

* changes:
  btif_config: Fix pointer to freed memory
  NIAP: Add a map to store the LTTKM
  NIAP: Use bluetooth keystore to encrypt/decrypt LTTKM.
  NIAP: implement bluetooth keystore interface.(2/2)
  NIAP: Add new argument to determine config checksum check result.(2/4)
  NIAP: Add keystore.proto for java layer usage.
  NIAP: remove keystore related code for now.
parents c5c9ca3c 3adb5c9c
Loading
Loading
Loading
Loading
+1 −17
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@ btifCommonIncludes = [
    "packages/modules/Bluetooth/system/utils/include",
    "packages/modules/Bluetooth/system/include",
    "system/libhwbinder/include",
    //"system/security/keystore/include",
    //"hardware/interfaces/keymaster/4.0/support/include",
]

// libbtif static library for target
@@ -73,7 +71,6 @@ cc_library_static {
        "src/btif_hf_client.cc",
        "src/btif_hh.cc",
        "src/btif_hd.cc",
        //"src/btif_keystore.cc",
        "src/btif_mce.cc",
        "src/btif_pan.cc",
        "src/btif_profile_queue.cc",
@@ -90,6 +87,7 @@ cc_library_static {
        "src/btif_storage.cc",
        "src/btif_uid.cc",
        "src/btif_util.cc",
        "src/btif_keystore.cc",
        "src/stack_manager.cc",
    ],
    header_libs: [
@@ -107,12 +105,6 @@ cc_library_static {
        "libhidlbase",
        "libutils",
        "libcrypto",
        //"android.hardware.keymaster@4.0",
        //"android.hardware.keymaster@3.0",
        //"libkeymaster4support",
        //"libkeystore_aidl",
        //"libkeystore_binder",
        //"libkeystore_parcelables",
    ],
    whole_static_libs: [
        "avrcp-target-service",
@@ -135,7 +127,6 @@ cc_test {
    include_dirs: btifCommonIncludes,
    srcs: [
        "test/btif_storage_test.cc",
        //"test/btif_keystore_test.cc"
    ],
    header_libs: ["libbluetooth_headers"],
    shared_libs: [
@@ -151,13 +142,6 @@ cc_test {
        "libprocessgroup",
        "libutils",
        "libcrypto",
        //"android.hardware.keymaster@4.0",
        //"android.hardware.keymaster@3.0",
        //"libkeymaster4support",
        //"libkeystore_aidl",
        //"libkeystore_binder",
        //"libkeystore_parcelables",
        //"libbinder",
    ],
    static_libs: [
        "libbt-bta",
+18 −2
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ bool is_restricted_mode(void);

/*******************************************************************************
 *
 * Function         is_single_user_mode_
 * Function         is_niap_mode_
 *
 * Description      Checks if BT was enabled in single user mode. In this
 *                  mode, use of keystore for key attestation of LTK is limitee
@@ -114,7 +114,23 @@ bool is_restricted_mode(void);
 * Returns          bool
 *
 ******************************************************************************/
bool is_single_user_mode(void);
bool is_niap_mode(void);

/*******************************************************************************
 *
 * Function         get_niap_config_compare_result
 *
 * Description      Get the niap config compare result for confirming the config
 *                  checksum compare result. When the niap mode doesn't enable,
 *                  it should be all pass (0b11).
 *                  Bit define:
 *                    CONFIG_FILE_COMPARE_PASS = 0b01
 *                    CONFIG_BACKUP_COMPARE_PASS = 0b10
 *
 * Returns          int
 *
 ******************************************************************************/
int get_niap_config_compare_result(void);

/*******************************************************************************
 *
+17 −62
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 Google, Inc.
/*
 * Copyright 2020 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:
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
@@ -13,58 +12,14 @@
 * 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 <base/logging.h>
#include <keystore/keystore_client_impl.h>
#include <mutex>

#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
#include "osi/include/config.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"

namespace bluetooth {
/**
 * Client wrapper to access AndroidKeystore.
 *
 * <p>Use to encrypt/decrypt data and store to disk.
 */
class BtifKeystore {
 public:
  /**
   * @param keystore_client injected pre-created client object for keystore
   */
  BtifKeystore(keystore::KeystoreClient* keystore_client);

  /**
   * Encrypts given data
   *
   * <p>Returns a string representation of the encrypted data
   *
   * @param data to be encrypted
   * @param flags for keystore
   */
  std::string Encrypt(const std::string& data, int32_t flags);
#include <hardware/bt_keystore.h>

  /**
   * Returns a decrypted string representation of the encrypted data or empty
   * string on error.
   *
   * @param input encrypted data
   */
  std::string Decrypt(const std::string& input_filename);
namespace bluetooth {
namespace bluetooth_keystore {

 private:
  std::unique_ptr<keystore::KeystoreClient> keystore_client_;
  std::mutex api_mutex_;
  keystore::KeyStoreNativeReturnCode GenerateKey(const std::string& name,
                                                 int32_t flags,
                                                 bool auth_bound);
};
BluetoothKeystoreInterface* getBluetoothKeystoreInterface();

}  // namespace bluetooth_keystore
}  // namespace bluetooth
 No newline at end of file
+19 −6
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@
#include "btif_debug_btsnoop.h"
#include "btif_debug_conn.h"
#include "btif_hf.h"
#include "btif_keystore.h"
#include "btif_storage.h"
#include "btsnoop.h"
#include "btsnoop_mem.h"
@@ -84,7 +85,9 @@ using bluetooth::hearing_aid::HearingAidInterface;

bt_callbacks_t* bt_hal_cbacks = NULL;
bool restricted_mode = false;
bool single_user_mode = false;
bool niap_mode = false;
const int CONFIG_COMPARE_ALL_PASS = 0b11;
int niap_config_compare_result = CONFIG_COMPARE_ALL_PASS;

/*******************************************************************************
 *  Externs
@@ -137,9 +140,9 @@ static bool is_profile(const char* p1, const char* p2) {
 ****************************************************************************/

static int init(bt_callbacks_t* callbacks, bool start_restricted,
                bool is_single_user_mode) {
  LOG_INFO("%s: start restricted = %d ; single user = %d", __func__,
           start_restricted, is_single_user_mode);
                bool is_niap_mode, int config_compare_result) {
  LOG_INFO("%s: start restricted = %d ; niap = %d, config compare result = %d",
           __func__, start_restricted, is_niap_mode, config_compare_result);

  if (bluetooth::shim::is_gd_shim_enabled()) {
    LOG_INFO("%s Enable Gd bluetooth functionality", __func__);
@@ -155,7 +158,9 @@ static int init(bt_callbacks_t* callbacks, bool start_restricted,

  bt_hal_cbacks = callbacks;
  restricted_mode = start_restricted;
  single_user_mode = is_single_user_mode;
  niap_mode = is_niap_mode;
  niap_config_compare_result = config_compare_result;

  stack_manager_get_interface()->init_stack();
  btif_debug_init();
  return BT_STATUS_SUCCESS;
@@ -178,7 +183,12 @@ static int disable(void) {
static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); }

bool is_restricted_mode() { return restricted_mode; }
bool is_single_user_mode() { return single_user_mode; }
bool is_niap_mode() { return niap_mode; }
// if niap mode disable, will always return CONFIG_COMPARE_ALL_PASS(0b11)
// indicate don't check config checksum.
int get_niap_config_compare_result() {
  return niap_mode ? niap_config_compare_result : CONFIG_COMPARE_ALL_PASS;
}

static int get_adapter_properties(void) {
  /* sanity check */
@@ -388,6 +398,9 @@ static const void* get_profile_interface(const char* profile_id) {

  if (is_profile(profile_id, BT_PROFILE_HEARING_AID_ID))
    return btif_hearing_aid_get_interface();

  if (is_profile(profile_id, BT_KEYSTORE_ID))
    return bluetooth::bluetooth_keystore::getBluetoothKeystoreInterface();
  return NULL;
}

+91 −124
Original line number Diff line number Diff line
@@ -35,12 +35,12 @@
#include <string>
#include <unordered_map>

#include <btif_keystore.h>
#include "bt_types.h"
#include "btcore/include/module.h"
#include "btif_api.h"
#include "btif_common.h"
#include "btif_config_transcode.h"
//#include "btif_keystore.h"
#include "btif_util.h"
#include "common/address_obfuscator.h"
#include "common/metric_id_allocator.h"
@@ -64,17 +64,11 @@
#define DISABLED "disabled"
static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";

// constexpr int kBufferSize = 400 * 10;  // initial file is ~400B

/*static bool use_key_attestation() {
  return getuid() == AID_BLUETOOTH && is_single_user_mode();
}*/

#define BT_CONFIG_METRICS_SECTION "Metrics"
#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
#define BT_CONFIG_METRICS_ID_KEY "MetricsId"

// using bluetooth::BtifKeystore;
using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface;
using bluetooth::common::AddressObfuscator;
using bluetooth::common::MetricIdAllocator;

@@ -86,8 +80,6 @@ static const char* CONFIG_LEGACY_FILE_PATH = "bt_config.xml";
#else   // !defined(OS_GENERIC)
static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
static const char* CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_config.bak";
static const char* CONFIG_FILE_CHECKSUM_PATH = "/data/misc/bluedroid/bt_config.conf.encrypted-checksum";
static const char* CONFIG_BACKUP_CHECKSUM_PATH = "/data/misc/bluedroid/bt_config.bak.encrypted-checksum";
static const char* CONFIG_LEGACY_FILE_PATH =
    "/data/misc/bluedroid/bt_config.xml";
#endif  // defined(OS_GENERIC)
@@ -99,13 +91,26 @@ static bool is_factory_reset(void);
static void delete_config_files(void);
static void btif_config_remove_unpaired(config_t* config);
static void btif_config_remove_restricted(config_t* config);
static std::unique_ptr<config_t> btif_config_open(const char* filename, const char* checksum_filename);
static std::unique_ptr<config_t> btif_config_open(const char* filename);

// Key attestation
// static std::string hash_file(const char* filename);
// static std::string read_checksum_file(const char* filename);
// static void write_checksum_file(const char* filename, const std::string&
// hash);
static bool config_checksum_pass(int check_bit) {
  return ((get_niap_config_compare_result() & check_bit) == check_bit);
}
static bool btif_is_niap_mode() {
  return getuid() == AID_BLUETOOTH && is_niap_mode();
}
static bool btif_in_encrypt_key_name_list(std::string key);

static const int CONFIG_FILE_COMPARE_PASS = 1;
static const int CONFIG_BACKUP_COMPARE_PASS = 2;
static const std::string ENCRYPTED_STR = "encrypted";
static const std::string CONFIG_FILE_PREFIX = "bt_config-origin";
static const std::string CONFIG_FILE_HASH = "hash";
static const int ENCRYPT_KEY_NAME_LIST_SIZE = 7;
static const std::string encrypt_key_name_list[] = {
    "LinkKey",      "LE_KEY_PENC", "LE_KEY_PID",  "LE_KEY_LID",
    "LE_KEY_PCSRK", "LE_KEY_LENC", "LE_KEY_LCSRK"};

static enum ConfigSource {
  NOT_LOADED,
@@ -136,6 +141,10 @@ static const storage_config_t* storage_config_get_interface() {
  }
}

static BluetoothKeystoreInterface* get_bluetooth_keystore_interface() {
  return bluetooth::bluetooth_keystore::getBluetoothKeystoreInterface();
}

// TODO(zachoverflow): Move these two functions out, because they are too
// specific for this file
// {grumpy-cat/no, monty-python/you-make-me-sad}
@@ -259,34 +268,31 @@ static std::recursive_mutex config_lock; // protects operations on |config|.
static std::unique_ptr<config_t> config;
static alarm_t* config_timer;

// static BtifKeystore btif_keystore(new keystore::KeystoreClientImpl);

// Module lifecycle functions

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

  if (is_factory_reset()) delete_config_files();
  /*if (is_factory_reset() ||
      (use_key_attestation() && !btif_keystore.DoesKeyExist()))
    delete_config_files();*/

  std::string file_source;

  config = btif_config_open(CONFIG_FILE_PATH, CONFIG_FILE_CHECKSUM_PATH);
  if (config_checksum_pass(CONFIG_FILE_COMPARE_PASS)) {
    config = btif_config_open(CONFIG_FILE_PATH);
    btif_config_source = ORIGINAL;
  }
  if (!config) {
    LOG_WARN("%s unable to load config file: %s; using backup.", __func__,
             CONFIG_FILE_PATH);
    remove(CONFIG_FILE_CHECKSUM_PATH);
    config = btif_config_open(CONFIG_BACKUP_PATH, CONFIG_BACKUP_CHECKSUM_PATH);
    if (config_checksum_pass(CONFIG_BACKUP_COMPARE_PASS)) {
      config = btif_config_open(CONFIG_BACKUP_PATH);
      btif_config_source = BACKUP;
      file_source = "Backup";
    }
  }
  if (!config) {
    LOG_WARN("%s unable to load backup; attempting to transcode legacy file.",
             __func__);
    remove(CONFIG_BACKUP_CHECKSUM_PATH);
    config = btif_config_transcode(CONFIG_LEGACY_FILE_PATH);
    btif_config_source = LEGACY;
    file_source = "Legacy";
@@ -350,25 +356,7 @@ error:
  return future_new_immediate(FUTURE_FAIL);
}

static std::unique_ptr<config_t> btif_config_open(const char* filename, const char* checksum_filename) {
  /*// START KEY ATTESTATION
  // Get hash of current file
  std::string current_hash = hash_file(filename);
  // Get stored hash
  std::string stored_hash = read_checksum_file(checksum_filename);
  if (stored_hash.empty()) {
    LOG(ERROR) << __func__ << ": stored_hash=<empty>";
    if (!current_hash.empty()) {
      write_checksum_file(checksum_filename, current_hash);
      stored_hash = read_checksum_file(checksum_filename);
    }
  }
  // Compare hashes
  if (current_hash != stored_hash) {
    return nullptr;
  }
  // END KEY ATTESTATION*/

static std::unique_ptr<config_t> btif_config_open(const char* filename) {
  std::unique_ptr<config_t> config =
      storage_config_get_interface()->config_new(filename);
  if (!config) return nullptr;
@@ -393,6 +381,7 @@ static future_t* clean_up(void) {
  config_timer = NULL;

  std::unique_lock<std::recursive_mutex> lock(config_lock);
  get_bluetooth_keystore_interface()->clear_map();
  MetricIdAllocator::GetInstance().Close();
  config.reset();
  return future_new_immediate(FUTURE_SUCCESS);
@@ -500,6 +489,12 @@ bool btif_config_set_str(const std::string& section, const std::string& key,
  return true;
}

static bool btif_in_encrypt_key_name_list(std::string key) {
  return std::find(encrypt_key_name_list,
                   encrypt_key_name_list + ENCRYPT_KEY_NAME_LIST_SIZE,
                   key) != (encrypt_key_name_list + ENCRYPT_KEY_NAME_LIST_SIZE);
}

bool btif_config_get_bin(const std::string& section, const std::string& key,
                         uint8_t* value, size_t* length) {
  CHECK(config != NULL);
@@ -507,16 +502,28 @@ bool btif_config_get_bin(const std::string& section, const std::string& key,
  CHECK(length != NULL);

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

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

  bool in_encrypt_key_name_list = btif_in_encrypt_key_name_list(key);
  bool is_key_encrypted = *value_str_from_config == ENCRYPTED_STR;
  std::string string;

  if (!value_str_from_config->empty() && in_encrypt_key_name_list &&
      is_key_encrypted) {
    string = get_bluetooth_keystore_interface()->get_key(section + "-" + key);
    value_str = &string;
  } else {
    value_str = value_str_from_config;
  }

  size_t value_len = value_str->length();
  if ((value_len % 2) != 0 || *length < (value_len / 2)) {
    LOG(WARNING) << ": value size not divisible by 2, size is " << value_len;
@@ -530,8 +537,22 @@ bool btif_config_get_bin(const std::string& section, const std::string& key,
    }

  const char* ptr = value_str->c_str();
  for (*length = 0; *ptr; ptr += 2, *length += 1)
  for (*length = 0; *ptr; ptr += 2, *length += 1) {
    sscanf(ptr, "%02hhx", &value[*length]);
  }

  if (btif_is_niap_mode()) {
    if (!value_str_from_config->empty() && in_encrypt_key_name_list &&
        !is_key_encrypted) {
      get_bluetooth_keystore_interface()->set_encrypt_key_or_remove_key(
          section + "-" + key, *value_str_from_config);
      config_set_string(config.get(), section, key, ENCRYPTED_STR);
    }
  } else {
    if (in_encrypt_key_name_list && is_key_encrypted) {
      config_set_string(config.get(), section, key, value_str->c_str());
    }
  }

  return true;
}
@@ -571,10 +592,20 @@ bool btif_config_set_bin(const std::string& section, const std::string& key,
    str[(i * 2) + 1] = lookup[value[i] & 0x0F];
  }

  std::string value_str;
  if ((length > 0) && btif_is_niap_mode() &&
      btif_in_encrypt_key_name_list(key)) {
    get_bluetooth_keystore_interface()->set_encrypt_key_or_remove_key(
        section + "-" + key, str);
    value_str = ENCRYPTED_STR;
  } else {
    value_str = str;
  }

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

  osi_free(str);
@@ -586,6 +617,10 @@ 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);

  if (is_niap_mode() && btif_in_encrypt_key_name_list(key)) {
    get_bluetooth_keystore_interface()->set_encrypt_key_or_remove_key(
        section + "-" + key, "");
  }
  std::unique_lock<std::recursive_mutex> lock(config_lock);
  return storage_config_get_interface()->config_remove_key(config.get(),
                                                           section, key);
@@ -620,12 +655,6 @@ bool btif_config_clear(void) {
      storage_config_get_interface()->config_save(*config, CONFIG_FILE_PATH);
  btif_config_source = RESET;

  /*// Save encrypted hash
  std::string current_hash = hash_file(CONFIG_FILE_PATH);
  if (!current_hash.empty()) {
    write_checksum_file(CONFIG_FILE_CHECKSUM_PATH, current_hash);
  }*/

  return ret;
}

@@ -643,16 +672,14 @@ static void btif_config_write(UNUSED_ATTR uint16_t event,

  std::unique_lock<std::recursive_mutex> lock(config_lock);
  rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
  rename(CONFIG_FILE_CHECKSUM_PATH, CONFIG_BACKUP_CHECKSUM_PATH);
  std::unique_ptr<config_t> config_paired =
      storage_config_get_interface()->config_new_clone(*config);
  btif_config_remove_unpaired(config_paired.get());
  storage_config_get_interface()->config_save(*config_paired, CONFIG_FILE_PATH);
  /*// Save hash
  std::string current_hash = hash_file(CONFIG_FILE_PATH);
  if (!current_hash.empty()) {
    write_checksum_file(CONFIG_FILE_CHECKSUM_PATH, current_hash);
  }*/
  if (btif_is_niap_mode()) {
    get_bluetooth_keystore_interface()->set_encrypt_key_or_remove_key(
        CONFIG_FILE_PREFIX, CONFIG_FILE_HASH);
  }
}

static void btif_config_remove_unpaired(config_t* conf) {
@@ -746,65 +773,5 @@ static bool is_factory_reset(void) {
static void delete_config_files(void) {
  remove(CONFIG_FILE_PATH);
  remove(CONFIG_BACKUP_PATH);
  // remove(CONFIG_FILE_CHECKSUM_PATH);
  // remove(CONFIG_BACKUP_CHECKSUM_PATH);
  osi_property_set("persist.bluetooth.factoryreset", "false");
}

/*static std::string hash_file(const char* filename) {
  if (!use_key_attestation()) {
    LOG(INFO) << __func__ << ": Disabled for multi-user";
    return DISABLED;
  }
  FILE* fp = fopen(filename, "rb");
  if (!fp) {
    LOG(ERROR) << __func__ << ": unable to open config file: '" << filename
               << "': " << strerror(errno);
    return "";
  }
  uint8_t hash[SHA256_DIGEST_LENGTH];
  SHA256_CTX sha256;
  SHA256_Init(&sha256);
  std::array<std::byte, kBufferSize> buffer;
  int bytes_read = 0;
  while ((bytes_read = fread(buffer.data(), 1, buffer.size(), fp))) {
    SHA256_Update(&sha256, buffer.data(), bytes_read);
  }
  SHA256_Final(hash, &sha256);
  std::stringstream ss;
  for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
    ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
  }
  fclose(fp);
  return ss.str();
}

static std::string read_checksum_file(const char* checksum_filename) {
  if (!use_key_attestation()) {
    LOG(INFO) << __func__ << ": Disabled for multi-user";
    return DISABLED;
  }
  std::string encrypted_hash = checksum_read(checksum_filename);
  if (encrypted_hash.empty()) {
    LOG(INFO) << __func__ << ": read empty hash.";
    return "";
  }
  return btif_keystore.Decrypt(encrypted_hash);
}

static void write_checksum_file(const char* checksum_filename,
                                const std::string& hash) {
  if (!use_key_attestation()) {
    LOG(INFO) << __func__
              << ": Disabled for multi-user, since config changed removing "
                 "checksums.";
    remove(CONFIG_FILE_CHECKSUM_PATH);
    remove(CONFIG_BACKUP_CHECKSUM_PATH);
    return;
  }
  std::string encrypted_checksum = btif_keystore.Encrypt(hash, 0);
  CHECK(!encrypted_checksum.empty())
      << __func__ << ": Failed encrypting checksum";
  CHECK(checksum_save(encrypted_checksum, checksum_filename))
      << __func__ << ": Failed to save checksum!";
}*/
Loading