Loading system/btif/src/btif_config.cc +90 −11 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <string> #include <string> #include <unordered_map> #include <unordered_map> #include <btif_keystore.h> #include "bt_types.h" #include "bt_types.h" #include "btcore/include/module.h" #include "btcore/include/module.h" #include "btif_api.h" #include "btif_api.h" Loading Loading @@ -67,6 +68,7 @@ static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S"; #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit" #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit" #define BT_CONFIG_METRICS_ID_KEY "MetricsId" #define BT_CONFIG_METRICS_ID_KEY "MetricsId" using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; using bluetooth::common::AddressObfuscator; using bluetooth::common::AddressObfuscator; using bluetooth::common::MetricIdAllocator; using bluetooth::common::MetricIdAllocator; Loading @@ -91,6 +93,25 @@ static void btif_config_remove_unpaired(config_t* config); static void btif_config_remove_restricted(config_t* config); static void btif_config_remove_restricted(config_t* config); static std::unique_ptr<config_t> btif_config_open(const char* filename); static std::unique_ptr<config_t> btif_config_open(const char* filename); // Key attestation 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 { static enum ConfigSource { NOT_LOADED, NOT_LOADED, ORIGINAL, ORIGINAL, Loading Loading @@ -120,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 // TODO(zachoverflow): Move these two functions out, because they are too // specific for this file // specific for this file // {grumpy-cat/no, monty-python/you-make-me-sad} // {grumpy-cat/no, monty-python/you-make-me-sad} Loading Loading @@ -253,15 +278,19 @@ static future_t* init(void) { std::string file_source; std::string file_source; if (config_checksum_pass(CONFIG_FILE_COMPARE_PASS)) { config = btif_config_open(CONFIG_FILE_PATH); config = btif_config_open(CONFIG_FILE_PATH); btif_config_source = ORIGINAL; btif_config_source = ORIGINAL; } if (!config) { if (!config) { LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.", LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.", __func__, CONFIG_FILE_PATH); __func__, CONFIG_FILE_PATH); if (config_checksum_pass(CONFIG_BACKUP_COMPARE_PASS)) { config = btif_config_open(CONFIG_BACKUP_PATH); config = btif_config_open(CONFIG_BACKUP_PATH); btif_config_source = BACKUP; btif_config_source = BACKUP; file_source = "Backup"; file_source = "Backup"; } } } if (!config) { if (!config) { LOG_WARN(LOG_TAG, LOG_WARN(LOG_TAG, "%s unable to load backup; attempting to transcode legacy file.", "%s unable to load backup; attempting to transcode legacy file.", Loading Loading @@ -462,6 +491,12 @@ bool btif_config_set_str(const std::string& section, const std::string& key, return true; 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, bool btif_config_get_bin(const std::string& section, const std::string& key, uint8_t* value, size_t* length) { uint8_t* value, size_t* length) { CHECK(config != NULL); CHECK(config != NULL); Loading @@ -469,16 +504,28 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, CHECK(length != NULL); CHECK(length != NULL); std::unique_lock<std::recursive_mutex> lock(config_lock); std::unique_lock<std::recursive_mutex> lock(config_lock); const std::string* value_str = const std::string* value_str; storage_config_get_interface()->config_get_string(*config, section, key, const std::string* value_str_from_config = NULL); config_get_string(*config, section, key, NULL); if (!value_str) { if (!value_str_from_config) { VLOG(1) << __func__ << ": cannot find string for section " << section VLOG(1) << __func__ << ": cannot find string for section " << section << ", key " << key; << ", key " << key; return false; 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; if (!value_str_from_config->empty() && in_encrypt_key_name_list && is_key_encrypted) { std::string 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(); size_t value_len = value_str->length(); if ((value_len % 2) != 0 || *length < (value_len / 2)) { if ((value_len % 2) != 0 || *length < (value_len / 2)) { LOG(WARNING) << ": value size not divisible by 2, size is " << value_len; LOG(WARNING) << ": value size not divisible by 2, size is " << value_len; Loading @@ -492,8 +539,22 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, } } const char* ptr = value_str->c_str(); 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]); 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; return true; } } Loading Loading @@ -533,10 +594,20 @@ bool btif_config_set_bin(const std::string& section, const std::string& key, str[(i * 2) + 1] = lookup[value[i] & 0x0F]; 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); std::unique_lock<std::recursive_mutex> lock(config_lock); storage_config_get_interface()->config_set_string(config.get(), section, storage_config_get_interface()->config_set_string(config.get(), section, key, str); key, value_str); } } osi_free(str); osi_free(str); Loading @@ -548,6 +619,10 @@ std::list<section_t>& btif_config_sections() { return config->sections; } bool btif_config_remove(const std::string& section, const std::string& key) { bool btif_config_remove(const std::string& section, const std::string& key) { CHECK(config != NULL); 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); std::unique_lock<std::recursive_mutex> lock(config_lock); return storage_config_get_interface()->config_remove_key(config.get(), return storage_config_get_interface()->config_remove_key(config.get(), section, key); section, key); Loading Loading @@ -603,6 +678,10 @@ static void btif_config_write(UNUSED_ATTR uint16_t event, storage_config_get_interface()->config_new_clone(*config); storage_config_get_interface()->config_new_clone(*config); btif_config_remove_unpaired(config_paired.get()); btif_config_remove_unpaired(config_paired.get()); storage_config_get_interface()->config_save(*config_paired, CONFIG_FILE_PATH); storage_config_get_interface()->config_save(*config_paired, CONFIG_FILE_PATH); 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) { static void btif_config_remove_unpaired(config_t* conf) { Loading Loading
system/btif/src/btif_config.cc +90 −11 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <string> #include <string> #include <unordered_map> #include <unordered_map> #include <btif_keystore.h> #include "bt_types.h" #include "bt_types.h" #include "btcore/include/module.h" #include "btcore/include/module.h" #include "btif_api.h" #include "btif_api.h" Loading Loading @@ -67,6 +68,7 @@ static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S"; #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit" #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit" #define BT_CONFIG_METRICS_ID_KEY "MetricsId" #define BT_CONFIG_METRICS_ID_KEY "MetricsId" using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; using bluetooth::common::AddressObfuscator; using bluetooth::common::AddressObfuscator; using bluetooth::common::MetricIdAllocator; using bluetooth::common::MetricIdAllocator; Loading @@ -91,6 +93,25 @@ static void btif_config_remove_unpaired(config_t* config); static void btif_config_remove_restricted(config_t* config); static void btif_config_remove_restricted(config_t* config); static std::unique_ptr<config_t> btif_config_open(const char* filename); static std::unique_ptr<config_t> btif_config_open(const char* filename); // Key attestation 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 { static enum ConfigSource { NOT_LOADED, NOT_LOADED, ORIGINAL, ORIGINAL, Loading Loading @@ -120,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 // TODO(zachoverflow): Move these two functions out, because they are too // specific for this file // specific for this file // {grumpy-cat/no, monty-python/you-make-me-sad} // {grumpy-cat/no, monty-python/you-make-me-sad} Loading Loading @@ -253,15 +278,19 @@ static future_t* init(void) { std::string file_source; std::string file_source; if (config_checksum_pass(CONFIG_FILE_COMPARE_PASS)) { config = btif_config_open(CONFIG_FILE_PATH); config = btif_config_open(CONFIG_FILE_PATH); btif_config_source = ORIGINAL; btif_config_source = ORIGINAL; } if (!config) { if (!config) { LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.", LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.", __func__, CONFIG_FILE_PATH); __func__, CONFIG_FILE_PATH); if (config_checksum_pass(CONFIG_BACKUP_COMPARE_PASS)) { config = btif_config_open(CONFIG_BACKUP_PATH); config = btif_config_open(CONFIG_BACKUP_PATH); btif_config_source = BACKUP; btif_config_source = BACKUP; file_source = "Backup"; file_source = "Backup"; } } } if (!config) { if (!config) { LOG_WARN(LOG_TAG, LOG_WARN(LOG_TAG, "%s unable to load backup; attempting to transcode legacy file.", "%s unable to load backup; attempting to transcode legacy file.", Loading Loading @@ -462,6 +491,12 @@ bool btif_config_set_str(const std::string& section, const std::string& key, return true; 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, bool btif_config_get_bin(const std::string& section, const std::string& key, uint8_t* value, size_t* length) { uint8_t* value, size_t* length) { CHECK(config != NULL); CHECK(config != NULL); Loading @@ -469,16 +504,28 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, CHECK(length != NULL); CHECK(length != NULL); std::unique_lock<std::recursive_mutex> lock(config_lock); std::unique_lock<std::recursive_mutex> lock(config_lock); const std::string* value_str = const std::string* value_str; storage_config_get_interface()->config_get_string(*config, section, key, const std::string* value_str_from_config = NULL); config_get_string(*config, section, key, NULL); if (!value_str) { if (!value_str_from_config) { VLOG(1) << __func__ << ": cannot find string for section " << section VLOG(1) << __func__ << ": cannot find string for section " << section << ", key " << key; << ", key " << key; return false; 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; if (!value_str_from_config->empty() && in_encrypt_key_name_list && is_key_encrypted) { std::string 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(); size_t value_len = value_str->length(); if ((value_len % 2) != 0 || *length < (value_len / 2)) { if ((value_len % 2) != 0 || *length < (value_len / 2)) { LOG(WARNING) << ": value size not divisible by 2, size is " << value_len; LOG(WARNING) << ": value size not divisible by 2, size is " << value_len; Loading @@ -492,8 +539,22 @@ bool btif_config_get_bin(const std::string& section, const std::string& key, } } const char* ptr = value_str->c_str(); 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]); 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; return true; } } Loading Loading @@ -533,10 +594,20 @@ bool btif_config_set_bin(const std::string& section, const std::string& key, str[(i * 2) + 1] = lookup[value[i] & 0x0F]; 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); std::unique_lock<std::recursive_mutex> lock(config_lock); storage_config_get_interface()->config_set_string(config.get(), section, storage_config_get_interface()->config_set_string(config.get(), section, key, str); key, value_str); } } osi_free(str); osi_free(str); Loading @@ -548,6 +619,10 @@ std::list<section_t>& btif_config_sections() { return config->sections; } bool btif_config_remove(const std::string& section, const std::string& key) { bool btif_config_remove(const std::string& section, const std::string& key) { CHECK(config != NULL); 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); std::unique_lock<std::recursive_mutex> lock(config_lock); return storage_config_get_interface()->config_remove_key(config.get(), return storage_config_get_interface()->config_remove_key(config.get(), section, key); section, key); Loading Loading @@ -603,6 +678,10 @@ static void btif_config_write(UNUSED_ATTR uint16_t event, storage_config_get_interface()->config_new_clone(*config); storage_config_get_interface()->config_new_clone(*config); btif_config_remove_unpaired(config_paired.get()); btif_config_remove_unpaired(config_paired.get()); storage_config_get_interface()->config_save(*config_paired, CONFIG_FILE_PATH); storage_config_get_interface()->config_save(*config_paired, CONFIG_FILE_PATH); 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) { static void btif_config_remove_unpaired(config_t* conf) { Loading