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