1 /******************************************************************************
2 *
3 * Copyright 2014 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #define LOG_TAG "bt_btif_config"
20
21 #include "btif_config.h"
22
23 #include <base/logging.h>
24 #include <openssl/rand.h>
25 #include <unistd.h>
26
27 #include <cctype>
28 #include <cstdio>
29 #include <cstring>
30 #include <ctime>
31 #include <functional>
32 #include <mutex>
33 #include <sstream>
34 #include <string>
35 #include <unordered_map>
36
37 #include "btcore/include/module.h"
38 #include "btif_api.h"
39 #include "btif_common.h"
40 #include "btif_config_cache.h"
41 #include "btif_keystore.h"
42 #include "btif_metrics_logging.h"
43 #include "common/address_obfuscator.h"
44 #include "common/metric_id_allocator.h"
45 #include "main/shim/config.h"
46 #include "main/shim/shim.h"
47 #include "osi/include/alarm.h"
48 #include "osi/include/allocator.h"
49 #include "osi/include/compat.h"
50 #include "osi/include/config.h"
51 #include "osi/include/log.h"
52 #include "osi/include/osi.h"
53 #include "osi/include/properties.h"
54 #include "raw_address.h"
55 #include "stack/include/bt_octets.h"
56
57 #define TEMPORARY_SECTION_CAPACITY 10000
58
59 #define INFO_SECTION "Info"
60 #define FILE_TIMESTAMP "TimeCreated"
61 #define FILE_SOURCE "FileSource"
62 #define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
63 #define DISABLED "disabled"
64
65 #define BT_CONFIG_METRICS_SECTION "Metrics"
66 #define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
67 #define BT_CONFIG_METRICS_ID_KEY "MetricsId"
68
69 using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface;
70 using bluetooth::common::AddressObfuscator;
71 using bluetooth::common::MetricIdAllocator;
72
73 // Key attestation
74 static const std::string ENCRYPTED_STR = "encrypted";
75 static const std::string CONFIG_FILE_PREFIX = "bt_config-origin";
76 static const std::string CONFIG_FILE_HASH = "hash";
77 static const std::string encrypt_key_name_list[] = {
78 "LinkKey", "LE_KEY_PENC", "LE_KEY_PID", "LE_KEY_LID",
79 "LE_KEY_PCSRK", "LE_KEY_LENC", "LE_KEY_LCSRK"};
80
81 static enum ConfigSource {
82 NOT_LOADED,
83 ORIGINAL,
84 BACKUP,
85 LEGACY,
86 NEW_FILE,
87 RESET
88 } btif_config_source = NOT_LOADED;
89
90 static char btif_config_time_created[TIME_STRING_LENGTH];
91
92 /**
93 * Read metrics salt from config file, if salt is invalid or does not exist,
94 * generate new one and save it to config
95 */
read_or_set_metrics_salt()96 static void read_or_set_metrics_salt() {
97 AddressObfuscator::Octet32 metrics_salt = {};
98 size_t metrics_salt_length = metrics_salt.size();
99 if (!btif_config_get_bin(BT_CONFIG_METRICS_SECTION,
100 BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
101 &metrics_salt_length)) {
102 LOG(WARNING) << __func__ << ": Failed to read metrics salt from config";
103 // Invalidate salt
104 metrics_salt.fill(0);
105 }
106 if (metrics_salt_length != metrics_salt.size()) {
107 LOG(ERROR) << __func__ << ": Metrics salt length incorrect, "
108 << metrics_salt_length << " instead of " << metrics_salt.size();
109 // Invalidate salt
110 metrics_salt.fill(0);
111 }
112 if (!AddressObfuscator::IsSaltValid(metrics_salt)) {
113 LOG(INFO) << __func__ << ": Metrics salt is invalid, creating new one";
114 if (RAND_bytes(metrics_salt.data(), metrics_salt.size()) != 1) {
115 LOG(FATAL) << __func__ << "Failed to generate salt for metrics";
116 }
117 if (!btif_config_set_bin(BT_CONFIG_METRICS_SECTION,
118 BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
119 metrics_salt.size())) {
120 LOG(FATAL) << __func__ << "Failed to write metrics salt to config";
121 }
122 }
123 AddressObfuscator::GetInstance()->Initialize(metrics_salt);
124 }
125
126 /**
127 * Initialize metric id allocator by reading metric_id from config by mac
128 * address. If there is no metric id for a mac address, then allocate it a new
129 * metric id.
130 */
init_metric_id_allocator()131 static void init_metric_id_allocator() {
132 std::unordered_map<RawAddress, int> paired_device_map;
133
134 // When user update the system, there will be devices paired with older
135 // version of android without a metric id.
136 std::vector<RawAddress> addresses_without_id;
137
138 for (const auto& mac_address : btif_config_get_paired_devices()) {
139 auto addr_str = mac_address.ToString();
140 // if the section name is a mac address
141 bool is_valid_id_found = false;
142 if (btif_config_exist(addr_str, BT_CONFIG_METRICS_ID_KEY)) {
143 // there is one metric id under this mac_address
144 int id = 0;
145 btif_config_get_int(addr_str, BT_CONFIG_METRICS_ID_KEY, &id);
146 if (is_valid_id_from_metric_id_allocator(id)) {
147 paired_device_map[mac_address] = id;
148 is_valid_id_found = true;
149 }
150 }
151 if (!is_valid_id_found) {
152 addresses_without_id.push_back(mac_address);
153 }
154 }
155
156 // Initialize MetricIdAllocator
157 MetricIdAllocator::Callback save_device_callback =
158 [](const RawAddress& address, const int id) {
159 return btif_config_set_int(address.ToString(), BT_CONFIG_METRICS_ID_KEY,
160 id);
161 };
162 MetricIdAllocator::Callback forget_device_callback =
163 [](const RawAddress& address, const int id) {
164 return btif_config_remove(address.ToString(), BT_CONFIG_METRICS_ID_KEY);
165 };
166 if (!init_metric_id_allocator(paired_device_map,
167 std::move(save_device_callback),
168 std::move(forget_device_callback))) {
169 LOG(FATAL) << __func__ << "Failed to initialize MetricIdAllocator";
170 }
171
172 // Add device_without_id
173 for (auto& address : addresses_without_id) {
174 allocate_metric_id_from_metric_id_allocator(address);
175 save_metric_id_from_metric_id_allocator(address);
176 }
177 }
178
179 static std::recursive_mutex config_lock; // protects operations on |config|.
180
181 // limited btif config cache capacity
182 static BtifConfigCache btif_config_cache(TEMPORARY_SECTION_CAPACITY);
183
184 // Module lifecycle functions
185
init(void)186 static future_t* init(void) {
187 CHECK(bluetooth::shim::is_gd_stack_started_up());
188 // TODO (b/158035889) Migrate metrics module to GD
189 read_or_set_metrics_salt();
190 init_metric_id_allocator();
191 return future_new_immediate(FUTURE_SUCCESS);
192 }
193
shut_down(void)194 static future_t* shut_down(void) {
195 return future_new_immediate(FUTURE_SUCCESS);
196 }
197
clean_up(void)198 static future_t* clean_up(void) {
199 CHECK(bluetooth::shim::is_gd_stack_started_up());
200 // GD storage module cleanup by itself
201 std::unique_lock<std::recursive_mutex> lock(config_lock);
202 close_metric_id_allocator();
203 return future_new_immediate(FUTURE_SUCCESS);
204 }
205
206 EXPORT_SYMBOL module_t btif_config_module = {.name = BTIF_CONFIG_MODULE,
207 .init = init,
208 .start_up = NULL,
209 .shut_down = shut_down,
210 .clean_up = clean_up};
211
btif_config_exist(const std::string & section,const std::string & key)212 bool btif_config_exist(const std::string& section, const std::string& key) {
213 CHECK(bluetooth::shim::is_gd_stack_started_up());
214 return bluetooth::shim::BtifConfigInterface::HasProperty(section, key);
215 }
216
btif_config_get_int(const std::string & section,const std::string & key,int * value)217 bool btif_config_get_int(const std::string& section, const std::string& key,
218 int* value) {
219 CHECK(bluetooth::shim::is_gd_stack_started_up());
220 return bluetooth::shim::BtifConfigInterface::GetInt(section, key, value);
221 }
222
btif_config_set_int(const std::string & section,const std::string & key,int value)223 bool btif_config_set_int(const std::string& section, const std::string& key,
224 int value) {
225 CHECK(bluetooth::shim::is_gd_stack_started_up());
226 return bluetooth::shim::BtifConfigInterface::SetInt(section, key, value);
227 }
228
btif_config_get_uint64(const std::string & section,const std::string & key,uint64_t * value)229 bool btif_config_get_uint64(const std::string& section, const std::string& key,
230 uint64_t* value) {
231 CHECK(bluetooth::shim::is_gd_stack_started_up());
232 return bluetooth::shim::BtifConfigInterface::GetUint64(section, key, value);
233 }
234
btif_config_set_uint64(const std::string & section,const std::string & key,uint64_t value)235 bool btif_config_set_uint64(const std::string& section, const std::string& key,
236 uint64_t value) {
237 CHECK(bluetooth::shim::is_gd_stack_started_up());
238 return bluetooth::shim::BtifConfigInterface::SetUint64(section, key, value);
239 }
240
241 /*******************************************************************************
242 *
243 * Function btif_config_get_str
244 *
245 * Description Get the string value associated with a particular section
246 * and key.
247 *
248 * section : The section name (i.e "Adapter")
249 * key : The key name (i.e "Address")
250 * value : A pointer to a buffer where we will store the value
251 * size_bytes : The size of the buffer we have available to
252 * write the value into. Will be updated upon
253 * returning to contain the number of bytes
254 * written.
255 *
256 * Returns True if a value was found, False otherwise.
257 *
258 ******************************************************************************/
259
btif_config_get_str(const std::string & section,const std::string & key,char * value,int * size_bytes)260 bool btif_config_get_str(const std::string& section, const std::string& key,
261 char* value, int* size_bytes) {
262 CHECK(bluetooth::shim::is_gd_stack_started_up());
263 return bluetooth::shim::BtifConfigInterface::GetStr(section, key, value,
264 size_bytes);
265 }
266
btif_config_set_str(const std::string & section,const std::string & key,const std::string & value)267 bool btif_config_set_str(const std::string& section, const std::string& key,
268 const std::string& value) {
269 CHECK(bluetooth::shim::is_gd_stack_started_up());
270 return bluetooth::shim::BtifConfigInterface::SetStr(section, key, value);
271 }
272
btif_config_get_bin(const std::string & section,const std::string & key,uint8_t * value,size_t * length)273 bool btif_config_get_bin(const std::string& section, const std::string& key,
274 uint8_t* value, size_t* length) {
275 CHECK(bluetooth::shim::is_gd_stack_started_up());
276 return bluetooth::shim::BtifConfigInterface::GetBin(section, key, value,
277 length);
278 }
279
btif_config_get_bin_length(const std::string & section,const std::string & key)280 size_t btif_config_get_bin_length(const std::string& section,
281 const std::string& key) {
282 CHECK(bluetooth::shim::is_gd_stack_started_up());
283 return bluetooth::shim::BtifConfigInterface::GetBinLength(section, key);
284 }
285
btif_config_set_bin(const std::string & section,const std::string & key,const uint8_t * value,size_t length)286 bool btif_config_set_bin(const std::string& section, const std::string& key,
287 const uint8_t* value, size_t length) {
288 CHECK(bluetooth::shim::is_gd_stack_started_up());
289 return bluetooth::shim::BtifConfigInterface::SetBin(section, key, value,
290 length);
291 }
292
btif_config_get_paired_devices()293 std::vector<RawAddress> btif_config_get_paired_devices() {
294 std::vector<std::string> names;
295 CHECK(bluetooth::shim::is_gd_stack_started_up());
296 names = bluetooth::shim::BtifConfigInterface::GetPersistentDevices();
297
298 std::vector<RawAddress> result;
299 result.reserve(names.size());
300 for (const auto& name : names) {
301 RawAddress addr = {};
302 // Gather up known devices from configuration section names
303 if (RawAddress::FromString(name, addr)) {
304 result.emplace_back(addr);
305 }
306 }
307 return result;
308 }
309
btif_config_remove(const std::string & section,const std::string & key)310 bool btif_config_remove(const std::string& section, const std::string& key) {
311 CHECK(bluetooth::shim::is_gd_stack_started_up());
312 return bluetooth::shim::BtifConfigInterface::RemoveProperty(section, key);
313 }
314
btif_config_clear(void)315 bool btif_config_clear(void) {
316 CHECK(bluetooth::shim::is_gd_stack_started_up());
317 bluetooth::shim::BtifConfigInterface::Clear();
318 return true;
319 }
320
btif_debug_config_dump(int fd)321 void btif_debug_config_dump(int fd) {
322 dprintf(fd, "\nBluetooth Config:\n");
323
324 dprintf(fd, " Config Source: ");
325 switch (btif_config_source) {
326 case NOT_LOADED:
327 dprintf(fd, "Not loaded\n");
328 break;
329 case ORIGINAL:
330 dprintf(fd, "Original file\n");
331 break;
332 case BACKUP:
333 dprintf(fd, "Backup file\n");
334 break;
335 case LEGACY:
336 dprintf(fd, "Legacy file\n");
337 break;
338 case NEW_FILE:
339 dprintf(fd, "New file\n");
340 break;
341 case RESET:
342 dprintf(fd, "Reset file\n");
343 break;
344 }
345
346 std::optional<std::string> file_source;
347 if (bluetooth::shim::is_gd_stack_started_up()) {
348 file_source =
349 bluetooth::shim::BtifConfigInterface::GetStr(INFO_SECTION, FILE_SOURCE);
350 } else {
351 file_source = btif_config_cache.GetString(INFO_SECTION, FILE_SOURCE);
352 }
353 if (!file_source) {
354 file_source.emplace("Original");
355 }
356 auto devices = btif_config_cache.GetPersistentSectionNames();
357 dprintf(fd, " Devices loaded: %zu\n", devices.size());
358 dprintf(fd, " File created/tagged: %s\n", btif_config_time_created);
359 dprintf(fd, " File source: %s\n", file_source->c_str());
360 }
361