1 /* keys_br.c - Bluetooth BR/EDR key handling */
2
3 /*
4 * Copyright (c) 2015-2016 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/kernel.h>
10 #include <string.h>
11 #include <zephyr/sys/atomic.h>
12 #include <zephyr/sys/util.h>
13
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/conn.h>
16 #include <zephyr/bluetooth/hci.h>
17 #include <zephyr/settings/settings.h>
18
19 #include "common/bt_str.h"
20
21 #include "host/hci_core.h"
22 #include "host/settings.h"
23 #include "host/keys.h"
24
25 #define LOG_LEVEL CONFIG_BT_KEYS_LOG_LEVEL
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(bt_keys_br);
28
29 static struct bt_keys_link_key key_pool[CONFIG_BT_MAX_PAIRED];
30
31 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
32 static uint32_t aging_counter_val;
33 static struct bt_keys_link_key *last_keys_updated;
34 #endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
35
bt_keys_find_link_key(const bt_addr_t * addr)36 struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr)
37 {
38 struct bt_keys_link_key *key;
39 int i;
40
41 LOG_DBG("%s", bt_addr_str(addr));
42
43 for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
44 key = &key_pool[i];
45
46 if (bt_addr_eq(&key->addr, addr)) {
47 return key;
48 }
49 }
50
51 return NULL;
52 }
53
bt_keys_get_link_key(const bt_addr_t * addr)54 struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr)
55 {
56 struct bt_keys_link_key *key;
57
58 key = bt_keys_find_link_key(addr);
59 if (key) {
60 return key;
61 }
62
63 key = bt_keys_find_link_key(BT_ADDR_ANY);
64 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
65 if (!key) {
66 int i;
67
68 key = &key_pool[0];
69 for (i = 1; i < ARRAY_SIZE(key_pool); i++) {
70 struct bt_keys_link_key *current = &key_pool[i];
71
72 if (current->aging_counter < key->aging_counter) {
73 key = current;
74 }
75 }
76
77 if (key) {
78 bt_keys_link_key_clear(key);
79 }
80 }
81 #endif
82
83 if (key) {
84 bt_addr_copy(&key->addr, addr);
85 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
86 key->aging_counter = ++aging_counter_val;
87 last_keys_updated = key;
88 #endif
89 LOG_DBG("created %p for %s", key, bt_addr_str(addr));
90 return key;
91 }
92
93 LOG_DBG("unable to create keys for %s", bt_addr_str(addr));
94
95 return NULL;
96 }
97
bt_keys_link_key_clear(struct bt_keys_link_key * link_key)98 void bt_keys_link_key_clear(struct bt_keys_link_key *link_key)
99 {
100 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
101 bt_addr_le_t le_addr;
102
103 le_addr.type = BT_ADDR_LE_PUBLIC;
104 bt_addr_copy(&le_addr.a, &link_key->addr);
105
106 bt_settings_delete_link_key(&le_addr);
107 }
108
109 LOG_DBG("%s", bt_addr_str(&link_key->addr));
110 (void)memset(link_key, 0, sizeof(*link_key));
111 }
112
bt_keys_link_key_clear_addr(const bt_addr_t * addr)113 void bt_keys_link_key_clear_addr(const bt_addr_t *addr)
114 {
115 int i;
116 struct bt_keys_link_key *key;
117
118 if (!addr) {
119 for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
120 key = &key_pool[i];
121 bt_keys_link_key_clear(key);
122 }
123 return;
124 }
125
126 key = bt_keys_find_link_key(addr);
127 if (key) {
128 bt_keys_link_key_clear(key);
129 }
130 }
131
bt_keys_link_key_store(struct bt_keys_link_key * link_key)132 void bt_keys_link_key_store(struct bt_keys_link_key *link_key)
133 {
134 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
135 int err;
136 bt_addr_le_t le_addr;
137
138 le_addr.type = BT_ADDR_LE_PUBLIC;
139 bt_addr_copy(&le_addr.a, &link_key->addr);
140
141 err = bt_settings_store_link_key(&le_addr, link_key->storage_start,
142 BT_KEYS_LINK_KEY_STORAGE_LEN);
143 if (err) {
144 LOG_ERR("Failed to save link key (err %d)", err);
145 }
146 }
147 }
148
bt_foreach_bond_br(void (* func)(const struct bt_bond_info * info,void * user_data),void * user_data)149 void bt_foreach_bond_br(void (*func)(const struct bt_bond_info *info, void *user_data),
150 void *user_data)
151 {
152 __ASSERT_NO_MSG(func != NULL);
153
154 for (size_t i = 0; i < ARRAY_SIZE(key_pool); i++) {
155 const struct bt_keys_link_key *key = &key_pool[i];
156
157 if (!bt_addr_eq(&key->addr, BT_ADDR_ANY)) {
158 struct bt_bond_info info;
159
160 info.addr.type = BT_ADDR_LE_PUBLIC;
161 bt_addr_copy(&info.addr.a, &key->addr);
162 func(&info, user_data);
163 }
164 }
165 }
166
167 #if defined(CONFIG_BT_SETTINGS)
168
link_key_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)169 static int link_key_set(const char *name, size_t len_rd,
170 settings_read_cb read_cb, void *cb_arg)
171 {
172 int err;
173 ssize_t len;
174 bt_addr_le_t le_addr;
175 struct bt_keys_link_key *link_key;
176 char val[BT_KEYS_LINK_KEY_STORAGE_LEN];
177
178 if (!name) {
179 LOG_ERR("Insufficient number of arguments");
180 return -EINVAL;
181 }
182
183 len = read_cb(cb_arg, val, sizeof(val));
184 if (len < 0) {
185 LOG_ERR("Failed to read value (err %zu)", len);
186 return -EINVAL;
187 }
188
189 LOG_DBG("name %s val %s", name, len ? bt_hex(val, sizeof(val)) : "(null)");
190
191 err = bt_settings_decode_key(name, &le_addr);
192 if (err) {
193 LOG_ERR("Unable to decode address %s", name);
194 return -EINVAL;
195 }
196
197 link_key = bt_keys_get_link_key(&le_addr.a);
198 if (len != BT_KEYS_LINK_KEY_STORAGE_LEN) {
199 if (link_key) {
200 bt_keys_link_key_clear(link_key);
201 LOG_DBG("Clear keys for %s", bt_addr_le_str(&le_addr));
202 } else {
203 LOG_WRN("Unable to find deleted keys for %s", bt_addr_le_str(&le_addr));
204 }
205
206 return 0;
207 }
208
209 memcpy(link_key->storage_start, val, len);
210 LOG_DBG("Successfully restored link key for %s", bt_addr_le_str(&le_addr));
211 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
212 if (aging_counter_val < link_key->aging_counter) {
213 aging_counter_val = link_key->aging_counter;
214 }
215 #endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
216
217 return 0;
218 }
219
220 SETTINGS_STATIC_HANDLER_DEFINE(bt_link_key, "bt/link_key", NULL, link_key_set,
221 NULL, NULL);
222
223 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
bt_keys_link_key_update_usage(const bt_addr_t * addr)224 void bt_keys_link_key_update_usage(const bt_addr_t *addr)
225 {
226 struct bt_keys_link_key *link_key = bt_keys_find_link_key(addr);
227
228 if (!link_key) {
229 return;
230 }
231
232 if (last_keys_updated == link_key) {
233 return;
234 }
235
236 link_key->aging_counter = ++aging_counter_val;
237 last_keys_updated = link_key;
238
239 LOG_DBG("Aging counter for %s is set to %u", bt_addr_str(addr), link_key->aging_counter);
240
241 if (IS_ENABLED(CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING)) {
242 bt_keys_link_key_store(link_key);
243 }
244 }
245 #endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
246
247 #endif /* defined(CONFIG_BT_SETTINGS) */
248