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 <bluetooth/log.h>
24 #include <openssl/rand.h>
25 #include <unistd.h>
26
27 #include <cstdio>
28 #include <cstring>
29 #include <ctime>
30 #include <mutex>
31 #include <string>
32 #include <unordered_map>
33
34 #include "btif_keystore.h"
35 #include "btif_metrics_logging.h"
36 #include "common/address_obfuscator.h"
37 #include "common/metric_id_allocator.h"
38 #include "main/shim/config.h"
39 #include "main/shim/shim.h"
40 #include "storage/config_keys.h"
41 #include "types/raw_address.h"
42
43 #define TEMPORARY_SECTION_CAPACITY 10000
44
45 #define INFO_SECTION "Info"
46 #define FILE_TIMESTAMP "TimeCreated"
47 #define FILE_SOURCE "FileSource"
48 #define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
49 #define DISABLED "disabled"
50
51 using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface;
52 using bluetooth::common::AddressObfuscator;
53 using bluetooth::common::MetricIdAllocator;
54 using namespace bluetooth;
55
56 // Key attestation
57 static const std::string ENCRYPTED_STR = "encrypted";
58 static const std::string CONFIG_FILE_PREFIX = "bt_config-origin";
59 static const std::string CONFIG_FILE_HASH = "hash";
60 static const std::string encrypt_key_name_list[] = {"LinkKey", "LE_KEY_PENC", "LE_KEY_PID",
61 "LE_KEY_LID", "LE_KEY_PCSRK", "LE_KEY_LENC",
62 "LE_KEY_LCSRK"};
63
64 /**
65 * Read metrics salt from config file, if salt is invalid or does not exist,
66 * generate new one and save it to config
67 */
read_or_set_metrics_salt()68 static void read_or_set_metrics_salt() {
69 AddressObfuscator::Octet32 metrics_salt = {};
70 size_t metrics_salt_length = metrics_salt.size();
71 if (!btif_config_get_bin(BTIF_STORAGE_SECTION_METRICS, BTIF_STORAGE_KEY_METRICS_SALT_256BIT,
72 metrics_salt.data(), &metrics_salt_length)) {
73 log::warn("Failed to read metrics salt from config");
74 // Invalidate salt
75 metrics_salt.fill(0);
76 }
77 if (metrics_salt_length != metrics_salt.size()) {
78 log::error("Metrics salt length incorrect, {} instead of {}", metrics_salt_length,
79 metrics_salt.size());
80 // Invalidate salt
81 metrics_salt.fill(0);
82 }
83 if (!AddressObfuscator::IsSaltValid(metrics_salt)) {
84 log::info("Metrics salt is invalid, creating new one");
85 if (RAND_bytes(metrics_salt.data(), metrics_salt.size()) != 1) {
86 log::fatal("Failed to generate salt for metrics");
87 }
88 if (!btif_config_set_bin(BTIF_STORAGE_SECTION_METRICS, BTIF_STORAGE_KEY_METRICS_SALT_256BIT,
89 metrics_salt.data(), metrics_salt.size())) {
90 log::fatal("Failed to write metrics salt to config");
91 }
92 }
93 AddressObfuscator::GetInstance()->Initialize(metrics_salt);
94 }
95
96 /**
97 * Initialize metric id allocator by reading metric_id from config by mac
98 * address. If there is no metric id for a mac address, then allocate it a new
99 * metric id.
100 */
init_metric_id_allocator()101 static void init_metric_id_allocator() {
102 std::unordered_map<RawAddress, int> paired_device_map;
103
104 // When user update the system, there will be devices paired with older
105 // version of android without a metric id.
106 std::vector<RawAddress> addresses_without_id;
107
108 for (const auto& mac_address : btif_config_get_paired_devices()) {
109 auto addr_str = mac_address.ToString();
110 // if the section name is a mac address
111 bool is_valid_id_found = false;
112 if (btif_config_exist(addr_str, BTIF_STORAGE_KEY_METRICS_ID_KEY)) {
113 // there is one metric id under this mac_address
114 int id = 0;
115 btif_config_get_int(addr_str, BTIF_STORAGE_KEY_METRICS_ID_KEY, &id);
116 if (is_valid_id_from_metric_id_allocator(id)) {
117 paired_device_map[mac_address] = id;
118 is_valid_id_found = true;
119 }
120 }
121 if (!is_valid_id_found) {
122 addresses_without_id.push_back(mac_address);
123 }
124 }
125
126 // Initialize MetricIdAllocator
127 MetricIdAllocator::Callback save_device_callback = [](const RawAddress& address, const int id) {
128 return btif_config_set_int(address.ToString(), BTIF_STORAGE_KEY_METRICS_ID_KEY, id);
129 };
130 MetricIdAllocator::Callback forget_device_callback = [](const RawAddress& address,
131 const int /* id */) {
132 return btif_config_remove(address.ToString(), BTIF_STORAGE_KEY_METRICS_ID_KEY);
133 };
134 if (!init_metric_id_allocator(paired_device_map, std::move(save_device_callback),
135 std::move(forget_device_callback))) {
136 log::fatal("Failed to initialize MetricIdAllocator");
137 }
138
139 // Add device_without_id
140 for (auto& address : addresses_without_id) {
141 allocate_metric_id_from_metric_id_allocator(address);
142 save_metric_id_from_metric_id_allocator(address);
143 }
144 }
145
146 static std::recursive_mutex config_lock; // protects operations on |config|.
147
148 // Module lifecycle functions
149
init(void)150 static future_t* init(void) {
151 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
152 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
153 // TODO (b/158035889) Migrate metrics module to GD
154 read_or_set_metrics_salt();
155 init_metric_id_allocator();
156 return future_new_immediate(FUTURE_SUCCESS);
157 }
158
shut_down(void)159 static future_t* shut_down(void) { return future_new_immediate(FUTURE_SUCCESS); }
160
clean_up(void)161 static future_t* clean_up(void) {
162 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
163 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
164 // GD storage module cleanup by itself
165 std::unique_lock<std::recursive_mutex> lock(config_lock);
166 close_metric_id_allocator();
167 return future_new_immediate(FUTURE_SUCCESS);
168 }
169
170 EXPORT_SYMBOL module_t btif_config_module = {.name = BTIF_CONFIG_MODULE,
171 .init = init,
172 .start_up = NULL,
173 .shut_down = shut_down,
174 .clean_up = clean_up};
175
btif_get_device_clockoffset(const RawAddress & bda,int * p_clock_offset)176 bool btif_get_device_clockoffset(const RawAddress& bda, int* p_clock_offset) {
177 if (p_clock_offset == NULL) {
178 return false;
179 }
180
181 std::string addrstr = bda.ToString();
182 const char* bd_addr_str = addrstr.c_str();
183
184 if (!btif_config_get_int(bd_addr_str, BTIF_STORAGE_KEY_CLOCK_OFFSET, p_clock_offset)) {
185 return false;
186 }
187
188 log::debug("Device [{}] clock_offset {}", bda, *p_clock_offset);
189 return true;
190 }
191
btif_set_device_clockoffset(const RawAddress & bda,int clock_offset)192 bool btif_set_device_clockoffset(const RawAddress& bda, int clock_offset) {
193 std::string addrstr = bda.ToString();
194 const char* bd_addr_str = addrstr.c_str();
195
196 if (!btif_config_set_int(bd_addr_str, BTIF_STORAGE_KEY_CLOCK_OFFSET, clock_offset)) {
197 return false;
198 }
199
200 log::debug("Device [{}] clock_offset {}", bda, clock_offset);
201 return true;
202 }
203
btif_config_exist(const std::string & section,const std::string & key)204 bool btif_config_exist(const std::string& section, const std::string& key) {
205 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
206 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
207 return bluetooth::shim::BtifConfigInterface::HasProperty(section, key);
208 }
209
btif_config_get_int(const std::string & section,const std::string & key,int * value)210 bool btif_config_get_int(const std::string& section, const std::string& key, int* value) {
211 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
212 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
213 return bluetooth::shim::BtifConfigInterface::GetInt(section, key, value);
214 }
215
btif_config_set_int(const std::string & section,const std::string & key,int value)216 bool btif_config_set_int(const std::string& section, const std::string& key, int value) {
217 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
218 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
219 return bluetooth::shim::BtifConfigInterface::SetInt(section, key, value);
220 }
221
btif_config_get_uint64(const std::string & section,const std::string & key,uint64_t * value)222 bool btif_config_get_uint64(const std::string& section, const std::string& key, uint64_t* value) {
223 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
224 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
225 return bluetooth::shim::BtifConfigInterface::GetUint64(section, key, value);
226 }
227
btif_config_set_uint64(const std::string & section,const std::string & key,uint64_t value)228 bool btif_config_set_uint64(const std::string& section, const std::string& key, uint64_t value) {
229 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
230 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
231 return bluetooth::shim::BtifConfigInterface::SetUint64(section, key, value);
232 }
233
234 /*******************************************************************************
235 *
236 * Function btif_config_get_str
237 *
238 * Description Get the string value associated with a particular section
239 * and key.
240 *
241 * section : The section name (i.e "Adapter")
242 * key : The key name (i.e "Address")
243 * value : A pointer to a buffer where we will store the value
244 * size_bytes : The size of the buffer we have available to
245 * write the value into. Will be updated upon
246 * returning to contain the number of bytes
247 * written.
248 *
249 * Returns True if a value was found, False otherwise.
250 *
251 ******************************************************************************/
252
btif_config_get_str(const std::string & section,const std::string & key,char * value,int * size_bytes)253 bool btif_config_get_str(const std::string& section, const std::string& key, char* value,
254 int* size_bytes) {
255 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
256 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
257 return bluetooth::shim::BtifConfigInterface::GetStr(section, key, value, size_bytes);
258 }
259
btif_config_set_str(const std::string & section,const std::string & key,const std::string & value)260 bool btif_config_set_str(const std::string& section, const std::string& key,
261 const std::string& value) {
262 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
263 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
264 return bluetooth::shim::BtifConfigInterface::SetStr(section, key, value);
265 }
266
btif_config_get_bin(const std::string & section,const std::string & key,uint8_t * value,size_t * length)267 bool btif_config_get_bin(const std::string& section, const std::string& key, uint8_t* value,
268 size_t* length) {
269 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
270 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
271 return bluetooth::shim::BtifConfigInterface::GetBin(section, key, value, length);
272 }
273
btif_config_get_bin_length(const std::string & section,const std::string & key)274 size_t btif_config_get_bin_length(const std::string& section, const std::string& key) {
275 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
276 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
277 return bluetooth::shim::BtifConfigInterface::GetBinLength(section, key);
278 }
279
btif_config_set_bin(const std::string & section,const std::string & key,const uint8_t * value,size_t length)280 bool btif_config_set_bin(const std::string& section, const std::string& key, const uint8_t* value,
281 size_t length) {
282 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
283 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
284 return bluetooth::shim::BtifConfigInterface::SetBin(section, key, value, length);
285 }
286
btif_config_get_paired_devices()287 std::vector<RawAddress> btif_config_get_paired_devices() {
288 std::vector<std::string> names;
289 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
290 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
291 names = bluetooth::shim::BtifConfigInterface::GetPersistentDevices();
292
293 std::vector<RawAddress> result;
294 result.reserve(names.size());
295 for (const auto& name : names) {
296 RawAddress addr = {};
297 // Gather up known devices from configuration section names
298 if (RawAddress::FromString(name, addr)) {
299 result.emplace_back(addr);
300 }
301 }
302 return result;
303 }
304
btif_config_remove(const std::string & section,const std::string & key)305 bool btif_config_remove(const std::string& section, const std::string& key) {
306 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
307 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
308 return bluetooth::shim::BtifConfigInterface::RemoveProperty(section, key);
309 }
310
btif_config_remove_device(const std::string & section)311 void btif_config_remove_device(const std::string& section) {
312 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
313 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
314 bluetooth::shim::BtifConfigInterface::RemoveSection(section);
315 }
316
btif_config_remove_device_with_key(const std::string & key)317 void btif_config_remove_device_with_key(const std::string& key) {
318 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
319 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
320 bluetooth::shim::BtifConfigInterface::RemoveSectionWithProperty(key);
321 }
322
btif_config_clear(void)323 bool btif_config_clear(void) {
324 log::assert_that(bluetooth::shim::is_gd_stack_started_up(),
325 "assert failed: bluetooth::shim::is_gd_stack_started_up()");
326 bluetooth::shim::BtifConfigInterface::Clear();
327 return true;
328 }
329