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