xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/beacon.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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