1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <errno.h>
10 #include <assert.h>
11 #include "os/os_mbuf.h"
12 #include "mesh/mesh.h"
13
14 #include "syscfg/syscfg.h"
15 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_BEACON))
16 #include "host/ble_hs_log.h"
17
18 #include "adv.h"
19 #include "mesh_priv.h"
20 #include "net.h"
21 #include "prov.h"
22 #include "crypto.h"
23 #include "beacon.h"
24 #include "foundation.h"
25
26 #define UNPROVISIONED_INTERVAL (K_SECONDS(5))
27 #define PROVISIONED_INTERVAL (K_SECONDS(10))
28
29 #define BEACON_TYPE_UNPROVISIONED 0x00
30 #define BEACON_TYPE_SECURE 0x01
31
32 /* 3 transmissions, 20ms interval */
33 #define UNPROV_XMIT BT_MESH_TRANSMIT(2, 20)
34
35 /* 1 transmission, 20ms interval */
36 #define PROV_XMIT BT_MESH_TRANSMIT(0, 20)
37
38 static struct k_delayed_work beacon_timer;
39
cache_check(u8_t data[21])40 static struct bt_mesh_subnet *cache_check(u8_t data[21])
41 {
42 int i;
43
44 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
45 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
46
47 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
48 continue;
49 }
50
51 if (!memcmp(sub->beacon_cache, data, 21)) {
52 return sub;
53 }
54 }
55
56 return NULL;
57 }
58
cache_add(u8_t data[21],struct bt_mesh_subnet * sub)59 static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
60 {
61 memcpy(sub->beacon_cache, data, 21);
62 }
63
beacon_complete(int err,void * user_data)64 static void beacon_complete(int err, void *user_data)
65 {
66 struct bt_mesh_subnet *sub = user_data;
67
68 BT_DBG("err %d", err);
69
70 sub->beacon_sent = k_uptime_get_32();
71 }
72
bt_mesh_beacon_create(struct bt_mesh_subnet * sub,struct os_mbuf * buf)73 void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
74 struct os_mbuf *buf)
75 {
76 u8_t flags = bt_mesh_net_flags(sub);
77 struct bt_mesh_subnet_keys *keys;
78
79 net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
80
81 if (sub->kr_flag) {
82 keys = &sub->keys[1];
83 } else {
84 keys = &sub->keys[0];
85 }
86
87 net_buf_simple_add_u8(buf, flags);
88
89 /* Network ID */
90 net_buf_simple_add_mem(buf, keys->net_id, 8);
91
92 /* IV Index */
93 net_buf_simple_add_be32(buf, bt_mesh.iv_index);
94
95 net_buf_simple_add_mem(buf, sub->auth, 8);
96
97 BT_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx,
98 flags, bt_hex(keys->net_id, 8));
99 BT_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index,
100 bt_hex(sub->auth, 8));
101 }
102
103 /* If the interval has passed or is within 5 seconds from now send a beacon */
104 #define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
105 K_SECONDS(5))
106
secure_beacon_send(void)107 static int secure_beacon_send(void)
108 {
109 static const struct bt_mesh_send_cb send_cb = {
110 .end = beacon_complete,
111 };
112 u32_t now = k_uptime_get_32();
113 int i;
114
115 BT_DBG("");
116
117 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
118 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
119 struct os_mbuf *buf;
120 u32_t time_diff;
121
122 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
123 continue;
124 }
125
126 time_diff = now - sub->beacon_sent;
127 if (time_diff < K_SECONDS(600) &&
128 time_diff < BEACON_THRESHOLD(sub)) {
129 continue;
130 }
131
132 buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
133 K_NO_WAIT);
134 if (!buf) {
135 BT_ERR("Unable to allocate beacon buffer");
136 return -ENOBUFS;
137 }
138
139 bt_mesh_beacon_create(sub, buf);
140
141 bt_mesh_adv_send(buf, &send_cb, sub);
142 net_buf_unref(buf);
143 }
144
145 return 0;
146 }
147
unprovisioned_beacon_send(void)148 static int unprovisioned_beacon_send(void)
149 {
150 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
151 const struct bt_mesh_prov *prov;
152 u8_t uri_hash[16] = { 0 };
153 struct os_mbuf *buf;
154 u16_t oob_info;
155
156 BT_DBG("unprovisioned_beacon_send");
157
158 buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT, K_NO_WAIT);
159 if (!buf) {
160 BT_ERR("Unable to allocate beacon buffer");
161 return -ENOBUFS;
162 }
163
164 prov = bt_mesh_prov_get();
165
166 net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED);
167 net_buf_add_mem(buf, prov->uuid, 16);
168
169 if (prov->uri && bt_mesh_s1(prov->uri, uri_hash) == 0) {
170 oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI;
171 } else {
172 oob_info = prov->oob_info;
173 }
174
175 net_buf_add_be16(buf, oob_info);
176 net_buf_add_mem(buf, uri_hash, 4);
177
178 bt_mesh_adv_send(buf, NULL, NULL);
179 net_buf_unref(buf);
180
181 if (prov->uri) {
182 size_t len;
183
184 buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT,
185 K_NO_WAIT);
186 if (!buf) {
187 BT_ERR("Unable to allocate URI buffer");
188 return -ENOBUFS;
189 }
190
191 len = strlen(prov->uri);
192 if (net_buf_tailroom(buf) < len) {
193 BT_WARN("Too long URI to fit advertising data");
194 } else {
195 net_buf_add_mem(buf, prov->uri, len);
196 bt_mesh_adv_send(buf, NULL, NULL);
197 }
198
199 net_buf_unref(buf);
200 }
201
202 #endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
203 return 0;
204 }
205
update_beacon_observation(void)206 static void update_beacon_observation(void)
207 {
208 static bool first_half;
209 int i;
210
211 /* Observation period is 20 seconds, whereas the beacon timer
212 * runs every 10 seconds. We process what's happened during the
213 * window only after the seconnd half.
214 */
215 first_half = !first_half;
216 if (first_half) {
217 return;
218 }
219
220 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
221 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
222
223 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
224 continue;
225 }
226
227 sub->beacons_last = sub->beacons_cur;
228 sub->beacons_cur = 0;
229 }
230 }
231
beacon_send(struct ble_npl_event * work)232 static void beacon_send(struct ble_npl_event *work)
233 {
234 /* Don't send anything if we have an active provisioning link */
235 if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) {
236 k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
237 return;
238 }
239
240 BT_DBG("");
241
242 if (bt_mesh_is_provisioned()) {
243 update_beacon_observation();
244 secure_beacon_send();
245
246 /* Only resubmit if beaconing is still enabled */
247 if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
248 bt_mesh.ivu_initiator) {
249 k_delayed_work_submit(&beacon_timer,
250 PROVISIONED_INTERVAL);
251 }
252 } else {
253 unprovisioned_beacon_send();
254 k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
255 }
256
257 }
258
secure_beacon_recv(struct os_mbuf * buf)259 static void secure_beacon_recv(struct os_mbuf *buf)
260 {
261 u8_t *data, *net_id, *auth;
262 struct bt_mesh_subnet *sub;
263 u32_t iv_index;
264 bool new_key, kr_change, iv_change;
265 u8_t flags;
266
267 if (buf->om_len < 21) {
268 BT_ERR("Too short secure beacon (len %u)", buf->om_len);
269 return;
270 }
271
272 sub = cache_check(buf->om_data);
273 if (sub) {
274 /* We've seen this beacon before - just update the stats */
275 goto update_stats;
276 }
277
278 /* So we can add to the cache if auth matches */
279 data = buf->om_data;
280
281 flags = net_buf_simple_pull_u8(buf);
282 net_id = buf->om_data;
283 net_buf_simple_pull(buf, 8);
284 iv_index = net_buf_simple_pull_be32(buf);
285 auth = buf->om_data;
286
287 BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
288 flags, bt_hex(net_id, 8), iv_index);
289
290 sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
291 if (!sub) {
292 BT_DBG("No subnet that matched beacon");
293 return;
294 }
295
296 if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
297 BT_WARN("Ignoring Phase 2 KR Update secured using old key");
298 return;
299 }
300
301 cache_add(data, sub);
302
303 /* If we have NetKey0 accept initiation only from it */
304 if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
305 sub->net_idx != BT_MESH_KEY_PRIMARY) {
306 BT_WARN("Ignoring secure beacon on non-primary subnet");
307 goto update_stats;
308 }
309
310 BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
311 sub->net_idx, iv_index, bt_mesh.iv_index);
312
313 if (bt_mesh.ivu_initiator &&
314 bt_mesh.iv_update == BT_MESH_IV_UPDATE(flags)) {
315 bt_mesh_beacon_ivu_initiator(false);
316 }
317
318 iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
319
320 kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
321 if (kr_change) {
322 bt_mesh_net_beacon_update(sub);
323 }
324
325 if (iv_change) {
326 /* Update all subnets */
327 bt_mesh_net_sec_update(NULL);
328 } else if (kr_change) {
329 /* Key Refresh without IV Update only impacts one subnet */
330 bt_mesh_net_sec_update(sub);
331 }
332
333 update_stats:
334 if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
335 sub->beacons_cur < 0xff) {
336 sub->beacons_cur++;
337 }
338 }
339
bt_mesh_beacon_recv(struct os_mbuf * buf)340 void bt_mesh_beacon_recv(struct os_mbuf *buf)
341 {
342 u8_t type;
343
344 BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
345
346 if (buf->om_len < 1) {
347 BT_ERR("Too short beacon");
348 return;
349 }
350
351 type = net_buf_simple_pull_u8(buf);
352 switch (type) {
353 case BEACON_TYPE_UNPROVISIONED:
354 BT_DBG("Ignoring unprovisioned device beacon");
355 break;
356 case BEACON_TYPE_SECURE:
357 secure_beacon_recv(buf);
358 break;
359 default:
360 BT_WARN("Unknown beacon type 0x%02x", type);
361 break;
362 }
363 }
364
bt_mesh_beacon_init(void)365 void bt_mesh_beacon_init(void)
366 {
367 k_delayed_work_init(&beacon_timer, beacon_send);
368 }
369
bt_mesh_beacon_ivu_initiator(bool enable)370 void bt_mesh_beacon_ivu_initiator(bool enable)
371 {
372 bt_mesh.ivu_initiator = enable;
373
374 if (enable) {
375 k_work_submit(&beacon_timer.work);
376 } else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
377 k_delayed_work_cancel(&beacon_timer);
378 }
379 }
380
bt_mesh_beacon_enable(void)381 void bt_mesh_beacon_enable(void)
382 {
383 int i;
384
385 if (!bt_mesh_is_provisioned()) {
386 k_work_submit(&beacon_timer.work);
387 return;
388 }
389
390 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
391 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
392
393 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
394 continue;
395 }
396
397 sub->beacons_last = 0;
398 sub->beacons_cur = 0;
399
400 bt_mesh_net_beacon_update(sub);
401 }
402
403 k_work_submit(&beacon_timer.work);
404 }
405
bt_mesh_beacon_disable(void)406 void bt_mesh_beacon_disable(void)
407 {
408 if (!bt_mesh.ivu_initiator) {
409 k_delayed_work_cancel(&beacon_timer);
410 }
411 }
412