1*042d53a7SEvalZero /* Bluetooth Mesh */
2*042d53a7SEvalZero
3*042d53a7SEvalZero /*
4*042d53a7SEvalZero * Copyright (c) 2017 Intel Corporation
5*042d53a7SEvalZero *
6*042d53a7SEvalZero * SPDX-License-Identifier: Apache-2.0
7*042d53a7SEvalZero */
8*042d53a7SEvalZero
9*042d53a7SEvalZero #include <string.h>
10*042d53a7SEvalZero #include <errno.h>
11*042d53a7SEvalZero #include <stdbool.h>
12*042d53a7SEvalZero
13*042d53a7SEvalZero #include "os/os_mbuf.h"
14*042d53a7SEvalZero #include "mesh/mesh.h"
15*042d53a7SEvalZero
16*042d53a7SEvalZero #include "syscfg/syscfg.h"
17*042d53a7SEvalZero #define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_NET)
18*042d53a7SEvalZero #include "host/ble_hs_log.h"
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include "crypto.h"
21*042d53a7SEvalZero #include "adv.h"
22*042d53a7SEvalZero #include "mesh_priv.h"
23*042d53a7SEvalZero #include "net.h"
24*042d53a7SEvalZero #include "lpn.h"
25*042d53a7SEvalZero #include "friend.h"
26*042d53a7SEvalZero #include "proxy.h"
27*042d53a7SEvalZero #include "transport.h"
28*042d53a7SEvalZero #include "access.h"
29*042d53a7SEvalZero #include "foundation.h"
30*042d53a7SEvalZero #include "beacon.h"
31*042d53a7SEvalZero #include "settings.h"
32*042d53a7SEvalZero #include "prov.h"
33*042d53a7SEvalZero
34*042d53a7SEvalZero /* Minimum valid Mesh Network PDU length. The Network headers
35*042d53a7SEvalZero * themselves take up 9 bytes. After that there is a minumum of 1 byte
36*042d53a7SEvalZero * payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1
37*042d53a7SEvalZero * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least
38*042d53a7SEvalZero * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes.
39*042d53a7SEvalZero */
40*042d53a7SEvalZero #define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8)
41*042d53a7SEvalZero
42*042d53a7SEvalZero /* Seq limit after IV Update is triggered */
43*042d53a7SEvalZero #define IV_UPDATE_SEQ_LIMIT 8000000
44*042d53a7SEvalZero
45*042d53a7SEvalZero #define IVI(pdu) ((pdu)[0] >> 7)
46*042d53a7SEvalZero #define NID(pdu) ((pdu)[0] & 0x7f)
47*042d53a7SEvalZero #define CTL(pdu) ((pdu)[1] >> 7)
48*042d53a7SEvalZero #define TTL(pdu) ((pdu)[1] & 0x7f)
49*042d53a7SEvalZero #define SEQ(pdu) (((u32_t)(pdu)[2] << 16) | \
50*042d53a7SEvalZero ((u32_t)(pdu)[3] << 8) | (u32_t)(pdu)[4]);
51*042d53a7SEvalZero #define SRC(pdu) (sys_get_be16(&(pdu)[5]))
52*042d53a7SEvalZero #define DST(pdu) (sys_get_be16(&(pdu)[7]))
53*042d53a7SEvalZero
54*042d53a7SEvalZero /* Determine how many friendship credentials we need */
55*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_MESH_FRIEND))
56*042d53a7SEvalZero #define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)
57*042d53a7SEvalZero #elif (MYNEWT_VAL(BLE_MESH_LOW_POWER))
58*042d53a7SEvalZero #define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
59*042d53a7SEvalZero #else
60*042d53a7SEvalZero #define FRIEND_CRED_COUNT 0
61*042d53a7SEvalZero #endif
62*042d53a7SEvalZero
63*042d53a7SEvalZero #if FRIEND_CRED_COUNT > 0
64*042d53a7SEvalZero static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
65*042d53a7SEvalZero #endif
66*042d53a7SEvalZero
67*042d53a7SEvalZero static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
68*042d53a7SEvalZero static u16_t msg_cache_next;
69*042d53a7SEvalZero
70*042d53a7SEvalZero /* Singleton network context (the implementation only supports one) */
71*042d53a7SEvalZero struct bt_mesh_net bt_mesh = {
72*042d53a7SEvalZero .local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue),
73*042d53a7SEvalZero .sub = {
74*042d53a7SEvalZero [0 ... (MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) - 1)] = {
75*042d53a7SEvalZero .net_idx = BT_MESH_KEY_UNUSED,
76*042d53a7SEvalZero }
77*042d53a7SEvalZero },
78*042d53a7SEvalZero .app_keys = {
79*042d53a7SEvalZero [0 ... (MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) - 1)] = {
80*042d53a7SEvalZero .net_idx = BT_MESH_KEY_UNUSED,
81*042d53a7SEvalZero }
82*042d53a7SEvalZero },
83*042d53a7SEvalZero };
84*042d53a7SEvalZero
85*042d53a7SEvalZero static u32_t dup_cache[4];
86*042d53a7SEvalZero static int dup_cache_next;
87*042d53a7SEvalZero
check_dup(struct os_mbuf * data)88*042d53a7SEvalZero static bool check_dup(struct os_mbuf *data)
89*042d53a7SEvalZero {
90*042d53a7SEvalZero const u8_t *tail = net_buf_simple_tail(data);
91*042d53a7SEvalZero u32_t val;
92*042d53a7SEvalZero int i;
93*042d53a7SEvalZero
94*042d53a7SEvalZero val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8);
95*042d53a7SEvalZero
96*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(dup_cache); i++) {
97*042d53a7SEvalZero if (dup_cache[i] == val) {
98*042d53a7SEvalZero return true;
99*042d53a7SEvalZero }
100*042d53a7SEvalZero }
101*042d53a7SEvalZero
102*042d53a7SEvalZero dup_cache[dup_cache_next++] = val;
103*042d53a7SEvalZero dup_cache_next %= ARRAY_SIZE(dup_cache);
104*042d53a7SEvalZero
105*042d53a7SEvalZero return false;
106*042d53a7SEvalZero }
107*042d53a7SEvalZero
msg_hash(struct bt_mesh_net_rx * rx,struct os_mbuf * pdu)108*042d53a7SEvalZero static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu)
109*042d53a7SEvalZero {
110*042d53a7SEvalZero u32_t hash1, hash2;
111*042d53a7SEvalZero
112*042d53a7SEvalZero /* Three least significant bytes of IVI + first byte of SEQ */
113*042d53a7SEvalZero hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2];
114*042d53a7SEvalZero
115*042d53a7SEvalZero /* Two last bytes of SEQ + SRC */
116*042d53a7SEvalZero memcpy(&hash2, &pdu->om_data[3], 4);
117*042d53a7SEvalZero
118*042d53a7SEvalZero return (u64_t)hash1 << 32 | (u64_t)hash2;
119*042d53a7SEvalZero }
120*042d53a7SEvalZero
msg_cache_match(struct bt_mesh_net_rx * rx,struct os_mbuf * pdu)121*042d53a7SEvalZero static bool msg_cache_match(struct bt_mesh_net_rx *rx,
122*042d53a7SEvalZero struct os_mbuf *pdu)
123*042d53a7SEvalZero {
124*042d53a7SEvalZero u64_t hash = msg_hash(rx, pdu);
125*042d53a7SEvalZero u16_t i;
126*042d53a7SEvalZero
127*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
128*042d53a7SEvalZero if (msg_cache[i] == hash) {
129*042d53a7SEvalZero return true;
130*042d53a7SEvalZero }
131*042d53a7SEvalZero }
132*042d53a7SEvalZero
133*042d53a7SEvalZero /* Add to the cache */
134*042d53a7SEvalZero msg_cache[msg_cache_next++] = hash;
135*042d53a7SEvalZero msg_cache_next %= ARRAY_SIZE(msg_cache);
136*042d53a7SEvalZero
137*042d53a7SEvalZero return false;
138*042d53a7SEvalZero }
139*042d53a7SEvalZero
bt_mesh_subnet_get(u16_t net_idx)140*042d53a7SEvalZero struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx)
141*042d53a7SEvalZero {
142*042d53a7SEvalZero int i;
143*042d53a7SEvalZero
144*042d53a7SEvalZero if (net_idx == BT_MESH_KEY_ANY) {
145*042d53a7SEvalZero return &bt_mesh.sub[0];
146*042d53a7SEvalZero }
147*042d53a7SEvalZero
148*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
149*042d53a7SEvalZero if (bt_mesh.sub[i].net_idx == net_idx) {
150*042d53a7SEvalZero return &bt_mesh.sub[i];
151*042d53a7SEvalZero }
152*042d53a7SEvalZero }
153*042d53a7SEvalZero
154*042d53a7SEvalZero return NULL;
155*042d53a7SEvalZero }
156*042d53a7SEvalZero
bt_mesh_net_keys_create(struct bt_mesh_subnet_keys * keys,const u8_t key[16])157*042d53a7SEvalZero int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
158*042d53a7SEvalZero const u8_t key[16])
159*042d53a7SEvalZero {
160*042d53a7SEvalZero u8_t p[] = { 0 };
161*042d53a7SEvalZero u8_t nid;
162*042d53a7SEvalZero int err;
163*042d53a7SEvalZero
164*042d53a7SEvalZero err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
165*042d53a7SEvalZero if (err) {
166*042d53a7SEvalZero BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
167*042d53a7SEvalZero return err;
168*042d53a7SEvalZero }
169*042d53a7SEvalZero
170*042d53a7SEvalZero memcpy(keys->net, key, 16);
171*042d53a7SEvalZero
172*042d53a7SEvalZero keys->nid = nid;
173*042d53a7SEvalZero
174*042d53a7SEvalZero BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
175*042d53a7SEvalZero BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));
176*042d53a7SEvalZero
177*042d53a7SEvalZero err = bt_mesh_k3(key, keys->net_id);
178*042d53a7SEvalZero if (err) {
179*042d53a7SEvalZero BT_ERR("Unable to generate Net ID");
180*042d53a7SEvalZero return err;
181*042d53a7SEvalZero }
182*042d53a7SEvalZero
183*042d53a7SEvalZero BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
184*042d53a7SEvalZero
185*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
186*042d53a7SEvalZero err = bt_mesh_identity_key(key, keys->identity);
187*042d53a7SEvalZero if (err) {
188*042d53a7SEvalZero BT_ERR("Unable to generate IdentityKey");
189*042d53a7SEvalZero return err;
190*042d53a7SEvalZero }
191*042d53a7SEvalZero
192*042d53a7SEvalZero BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
193*042d53a7SEvalZero #endif /* GATT_PROXY */
194*042d53a7SEvalZero
195*042d53a7SEvalZero err = bt_mesh_beacon_key(key, keys->beacon);
196*042d53a7SEvalZero if (err) {
197*042d53a7SEvalZero BT_ERR("Unable to generate beacon key");
198*042d53a7SEvalZero return err;
199*042d53a7SEvalZero }
200*042d53a7SEvalZero
201*042d53a7SEvalZero BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
202*042d53a7SEvalZero
203*042d53a7SEvalZero return 0;
204*042d53a7SEvalZero }
205*042d53a7SEvalZero
206*042d53a7SEvalZero #if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) || \
207*042d53a7SEvalZero (MYNEWT_VAL(BLE_MESH_FRIEND)))
friend_cred_set(struct friend_cred * cred,u8_t idx,const u8_t net_key[16])208*042d53a7SEvalZero int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
209*042d53a7SEvalZero {
210*042d53a7SEvalZero u16_t lpn_addr, frnd_addr;
211*042d53a7SEvalZero int err;
212*042d53a7SEvalZero u8_t p[9];
213*042d53a7SEvalZero
214*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
215*042d53a7SEvalZero if (cred->addr == bt_mesh.lpn.frnd) {
216*042d53a7SEvalZero lpn_addr = bt_mesh_primary_addr();
217*042d53a7SEvalZero frnd_addr = cred->addr;
218*042d53a7SEvalZero } else {
219*042d53a7SEvalZero lpn_addr = cred->addr;
220*042d53a7SEvalZero frnd_addr = bt_mesh_primary_addr();
221*042d53a7SEvalZero }
222*042d53a7SEvalZero #else
223*042d53a7SEvalZero lpn_addr = cred->addr;
224*042d53a7SEvalZero frnd_addr = bt_mesh_primary_addr();
225*042d53a7SEvalZero #endif
226*042d53a7SEvalZero
227*042d53a7SEvalZero BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr);
228*042d53a7SEvalZero BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter,
229*042d53a7SEvalZero cred->frnd_counter);
230*042d53a7SEvalZero
231*042d53a7SEvalZero p[0] = 0x01;
232*042d53a7SEvalZero sys_put_be16(lpn_addr, p + 1);
233*042d53a7SEvalZero sys_put_be16(frnd_addr, p + 3);
234*042d53a7SEvalZero sys_put_be16(cred->lpn_counter, p + 5);
235*042d53a7SEvalZero sys_put_be16(cred->frnd_counter, p + 7);
236*042d53a7SEvalZero
237*042d53a7SEvalZero err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid,
238*042d53a7SEvalZero cred->cred[idx].enc, cred->cred[idx].privacy);
239*042d53a7SEvalZero if (err) {
240*042d53a7SEvalZero BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
241*042d53a7SEvalZero return err;
242*042d53a7SEvalZero }
243*042d53a7SEvalZero
244*042d53a7SEvalZero BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid,
245*042d53a7SEvalZero bt_hex(cred->cred[idx].enc, 16));
246*042d53a7SEvalZero BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16));
247*042d53a7SEvalZero
248*042d53a7SEvalZero return 0;
249*042d53a7SEvalZero }
250*042d53a7SEvalZero
friend_cred_refresh(u16_t net_idx)251*042d53a7SEvalZero void friend_cred_refresh(u16_t net_idx)
252*042d53a7SEvalZero {
253*042d53a7SEvalZero int i;
254*042d53a7SEvalZero
255*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
256*042d53a7SEvalZero struct friend_cred *cred = &friend_cred[i];
257*042d53a7SEvalZero
258*042d53a7SEvalZero if (cred->addr != BT_MESH_ADDR_UNASSIGNED &&
259*042d53a7SEvalZero cred->net_idx == net_idx) {
260*042d53a7SEvalZero memcpy(&cred->cred[0], &cred->cred[1],
261*042d53a7SEvalZero sizeof(cred->cred[0]));
262*042d53a7SEvalZero }
263*042d53a7SEvalZero }
264*042d53a7SEvalZero }
265*042d53a7SEvalZero
friend_cred_update(struct bt_mesh_subnet * sub)266*042d53a7SEvalZero int friend_cred_update(struct bt_mesh_subnet *sub)
267*042d53a7SEvalZero {
268*042d53a7SEvalZero int err, i;
269*042d53a7SEvalZero
270*042d53a7SEvalZero BT_DBG("net_idx 0x%04x", sub->net_idx);
271*042d53a7SEvalZero
272*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
273*042d53a7SEvalZero struct friend_cred *cred = &friend_cred[i];
274*042d53a7SEvalZero
275*042d53a7SEvalZero if (cred->addr == BT_MESH_ADDR_UNASSIGNED ||
276*042d53a7SEvalZero cred->net_idx != sub->net_idx) {
277*042d53a7SEvalZero continue;
278*042d53a7SEvalZero }
279*042d53a7SEvalZero
280*042d53a7SEvalZero err = friend_cred_set(cred, 1, sub->keys[1].net);
281*042d53a7SEvalZero if (err) {
282*042d53a7SEvalZero return err;
283*042d53a7SEvalZero }
284*042d53a7SEvalZero }
285*042d53a7SEvalZero
286*042d53a7SEvalZero return 0;
287*042d53a7SEvalZero }
288*042d53a7SEvalZero
friend_cred_create(struct bt_mesh_subnet * sub,u16_t addr,u16_t lpn_counter,u16_t frnd_counter)289*042d53a7SEvalZero struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
290*042d53a7SEvalZero u16_t lpn_counter, u16_t frnd_counter)
291*042d53a7SEvalZero {
292*042d53a7SEvalZero struct friend_cred *cred;
293*042d53a7SEvalZero int i, err;
294*042d53a7SEvalZero
295*042d53a7SEvalZero BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
296*042d53a7SEvalZero
297*042d53a7SEvalZero for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
298*042d53a7SEvalZero if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
299*042d53a7SEvalZero (friend_cred[i].addr == addr &&
300*042d53a7SEvalZero friend_cred[i].net_idx == sub->net_idx)) {
301*042d53a7SEvalZero cred = &friend_cred[i];
302*042d53a7SEvalZero break;
303*042d53a7SEvalZero }
304*042d53a7SEvalZero }
305*042d53a7SEvalZero
306*042d53a7SEvalZero if (!cred) {
307*042d53a7SEvalZero BT_WARN("No free friend credential slots");
308*042d53a7SEvalZero return NULL;
309*042d53a7SEvalZero }
310*042d53a7SEvalZero
311*042d53a7SEvalZero cred->net_idx = sub->net_idx;
312*042d53a7SEvalZero cred->addr = addr;
313*042d53a7SEvalZero cred->lpn_counter = lpn_counter;
314*042d53a7SEvalZero cred->frnd_counter = frnd_counter;
315*042d53a7SEvalZero
316*042d53a7SEvalZero err = friend_cred_set(cred, 0, sub->keys[0].net);
317*042d53a7SEvalZero if (err) {
318*042d53a7SEvalZero friend_cred_clear(cred);
319*042d53a7SEvalZero return NULL;
320*042d53a7SEvalZero }
321*042d53a7SEvalZero
322*042d53a7SEvalZero if (sub->kr_flag) {
323*042d53a7SEvalZero err = friend_cred_set(cred, 1, sub->keys[1].net);
324*042d53a7SEvalZero if (err) {
325*042d53a7SEvalZero friend_cred_clear(cred);
326*042d53a7SEvalZero return NULL;
327*042d53a7SEvalZero }
328*042d53a7SEvalZero }
329*042d53a7SEvalZero
330*042d53a7SEvalZero return cred;
331*042d53a7SEvalZero }
332*042d53a7SEvalZero
friend_cred_clear(struct friend_cred * cred)333*042d53a7SEvalZero void friend_cred_clear(struct friend_cred *cred)
334*042d53a7SEvalZero {
335*042d53a7SEvalZero cred->net_idx = BT_MESH_KEY_UNUSED;
336*042d53a7SEvalZero cred->addr = BT_MESH_ADDR_UNASSIGNED;
337*042d53a7SEvalZero cred->lpn_counter = 0;
338*042d53a7SEvalZero cred->frnd_counter = 0;
339*042d53a7SEvalZero memset(cred->cred, 0, sizeof(cred->cred));
340*042d53a7SEvalZero }
341*042d53a7SEvalZero
friend_cred_del(u16_t net_idx,u16_t addr)342*042d53a7SEvalZero int friend_cred_del(u16_t net_idx, u16_t addr)
343*042d53a7SEvalZero {
344*042d53a7SEvalZero int i;
345*042d53a7SEvalZero
346*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
347*042d53a7SEvalZero struct friend_cred *cred = &friend_cred[i];
348*042d53a7SEvalZero
349*042d53a7SEvalZero if (cred->addr == addr && cred->net_idx == net_idx) {
350*042d53a7SEvalZero friend_cred_clear(cred);
351*042d53a7SEvalZero return 0;
352*042d53a7SEvalZero }
353*042d53a7SEvalZero }
354*042d53a7SEvalZero
355*042d53a7SEvalZero return -ENOENT;
356*042d53a7SEvalZero }
357*042d53a7SEvalZero
friend_cred_get(struct bt_mesh_subnet * sub,u16_t addr,u8_t * nid,const u8_t ** enc,const u8_t ** priv)358*042d53a7SEvalZero int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
359*042d53a7SEvalZero const u8_t **enc, const u8_t **priv)
360*042d53a7SEvalZero {
361*042d53a7SEvalZero int i;
362*042d53a7SEvalZero
363*042d53a7SEvalZero BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
364*042d53a7SEvalZero
365*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
366*042d53a7SEvalZero struct friend_cred *cred = &friend_cred[i];
367*042d53a7SEvalZero
368*042d53a7SEvalZero if (cred->net_idx != sub->net_idx) {
369*042d53a7SEvalZero continue;
370*042d53a7SEvalZero }
371*042d53a7SEvalZero
372*042d53a7SEvalZero if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) {
373*042d53a7SEvalZero continue;
374*042d53a7SEvalZero }
375*042d53a7SEvalZero
376*042d53a7SEvalZero if (nid) {
377*042d53a7SEvalZero *nid = cred->cred[sub->kr_flag].nid;
378*042d53a7SEvalZero }
379*042d53a7SEvalZero
380*042d53a7SEvalZero if (enc) {
381*042d53a7SEvalZero *enc = cred->cred[sub->kr_flag].enc;
382*042d53a7SEvalZero }
383*042d53a7SEvalZero
384*042d53a7SEvalZero if (priv) {
385*042d53a7SEvalZero *priv = cred->cred[sub->kr_flag].privacy;
386*042d53a7SEvalZero }
387*042d53a7SEvalZero
388*042d53a7SEvalZero return 0;
389*042d53a7SEvalZero }
390*042d53a7SEvalZero
391*042d53a7SEvalZero return -ENOENT;
392*042d53a7SEvalZero }
393*042d53a7SEvalZero #else
friend_cred_get(struct bt_mesh_subnet * sub,u16_t addr,u8_t * nid,const u8_t ** enc,const u8_t ** priv)394*042d53a7SEvalZero int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
395*042d53a7SEvalZero const u8_t **enc, const u8_t **priv)
396*042d53a7SEvalZero {
397*042d53a7SEvalZero return -ENOENT;
398*042d53a7SEvalZero }
399*042d53a7SEvalZero #endif /* FRIEND || LOW_POWER */
400*042d53a7SEvalZero
bt_mesh_net_flags(struct bt_mesh_subnet * sub)401*042d53a7SEvalZero u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
402*042d53a7SEvalZero {
403*042d53a7SEvalZero u8_t flags = 0x00;
404*042d53a7SEvalZero
405*042d53a7SEvalZero if (sub && sub->kr_flag) {
406*042d53a7SEvalZero flags |= BT_MESH_NET_FLAG_KR;
407*042d53a7SEvalZero }
408*042d53a7SEvalZero
409*042d53a7SEvalZero if (bt_mesh.iv_update) {
410*042d53a7SEvalZero flags |= BT_MESH_NET_FLAG_IVU;
411*042d53a7SEvalZero }
412*042d53a7SEvalZero
413*042d53a7SEvalZero return flags;
414*042d53a7SEvalZero }
415*042d53a7SEvalZero
bt_mesh_net_beacon_update(struct bt_mesh_subnet * sub)416*042d53a7SEvalZero int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub)
417*042d53a7SEvalZero {
418*042d53a7SEvalZero u8_t flags = bt_mesh_net_flags(sub);
419*042d53a7SEvalZero struct bt_mesh_subnet_keys *keys;
420*042d53a7SEvalZero
421*042d53a7SEvalZero if (sub->kr_flag) {
422*042d53a7SEvalZero BT_DBG("NetIndex %u Using new key", sub->net_idx);
423*042d53a7SEvalZero keys = &sub->keys[1];
424*042d53a7SEvalZero } else {
425*042d53a7SEvalZero BT_DBG("NetIndex %u Using current key", sub->net_idx);
426*042d53a7SEvalZero keys = &sub->keys[0];
427*042d53a7SEvalZero }
428*042d53a7SEvalZero
429*042d53a7SEvalZero BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
430*042d53a7SEvalZero
431*042d53a7SEvalZero return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
432*042d53a7SEvalZero bt_mesh.iv_index, sub->auth);
433*042d53a7SEvalZero }
434*042d53a7SEvalZero
bt_mesh_net_create(u16_t idx,u8_t flags,const u8_t key[16],u32_t iv_index)435*042d53a7SEvalZero int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
436*042d53a7SEvalZero u32_t iv_index)
437*042d53a7SEvalZero {
438*042d53a7SEvalZero struct bt_mesh_subnet *sub;
439*042d53a7SEvalZero int err;
440*042d53a7SEvalZero
441*042d53a7SEvalZero BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index);
442*042d53a7SEvalZero
443*042d53a7SEvalZero BT_DBG("NetKey %s", bt_hex(key, 16));
444*042d53a7SEvalZero
445*042d53a7SEvalZero if (bt_mesh.valid) {
446*042d53a7SEvalZero return -EALREADY;
447*042d53a7SEvalZero }
448*042d53a7SEvalZero
449*042d53a7SEvalZero memset(msg_cache, 0, sizeof(msg_cache));
450*042d53a7SEvalZero msg_cache_next = 0;
451*042d53a7SEvalZero
452*042d53a7SEvalZero sub = &bt_mesh.sub[0];
453*042d53a7SEvalZero
454*042d53a7SEvalZero sub->kr_flag = BT_MESH_KEY_REFRESH(flags);
455*042d53a7SEvalZero if (sub->kr_flag) {
456*042d53a7SEvalZero err = bt_mesh_net_keys_create(&sub->keys[1], key);
457*042d53a7SEvalZero if (err) {
458*042d53a7SEvalZero return -EIO;
459*042d53a7SEvalZero }
460*042d53a7SEvalZero
461*042d53a7SEvalZero sub->kr_phase = BT_MESH_KR_PHASE_2;
462*042d53a7SEvalZero } else {
463*042d53a7SEvalZero err = bt_mesh_net_keys_create(&sub->keys[0], key);
464*042d53a7SEvalZero if (err) {
465*042d53a7SEvalZero return -EIO;
466*042d53a7SEvalZero }
467*042d53a7SEvalZero }
468*042d53a7SEvalZero
469*042d53a7SEvalZero bt_mesh.valid = 1;
470*042d53a7SEvalZero sub->net_idx = idx;
471*042d53a7SEvalZero
472*042d53a7SEvalZero if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
473*042d53a7SEvalZero sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
474*042d53a7SEvalZero } else {
475*042d53a7SEvalZero sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
476*042d53a7SEvalZero }
477*042d53a7SEvalZero
478*042d53a7SEvalZero bt_mesh.iv_index = iv_index;
479*042d53a7SEvalZero bt_mesh.iv_update = BT_MESH_IV_UPDATE(flags);
480*042d53a7SEvalZero
481*042d53a7SEvalZero /* Set minimum required hours, since the 96-hour minimum requirement
482*042d53a7SEvalZero * doesn't apply straight after provisioning (since we can't know how
483*042d53a7SEvalZero * long has actually passed since the network changed its state).
484*042d53a7SEvalZero */
485*042d53a7SEvalZero bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
486*042d53a7SEvalZero
487*042d53a7SEvalZero /* Make sure we have valid beacon data to be sent */
488*042d53a7SEvalZero bt_mesh_net_beacon_update(sub);
489*042d53a7SEvalZero
490*042d53a7SEvalZero return 0;
491*042d53a7SEvalZero }
492*042d53a7SEvalZero
bt_mesh_net_revoke_keys(struct bt_mesh_subnet * sub)493*042d53a7SEvalZero void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub)
494*042d53a7SEvalZero {
495*042d53a7SEvalZero int i;
496*042d53a7SEvalZero
497*042d53a7SEvalZero BT_DBG("idx 0x%04x", sub->net_idx);
498*042d53a7SEvalZero
499*042d53a7SEvalZero memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
500*042d53a7SEvalZero
501*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
502*042d53a7SEvalZero struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
503*042d53a7SEvalZero
504*042d53a7SEvalZero if (key->net_idx != sub->net_idx || !key->updated) {
505*042d53a7SEvalZero continue;
506*042d53a7SEvalZero }
507*042d53a7SEvalZero
508*042d53a7SEvalZero memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0]));
509*042d53a7SEvalZero key->updated = false;
510*042d53a7SEvalZero }
511*042d53a7SEvalZero }
512*042d53a7SEvalZero
bt_mesh_kr_update(struct bt_mesh_subnet * sub,u8_t new_kr,bool new_key)513*042d53a7SEvalZero bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key)
514*042d53a7SEvalZero {
515*042d53a7SEvalZero if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) {
516*042d53a7SEvalZero BT_WARN("KR change in normal operation. Are we blacklisted?");
517*042d53a7SEvalZero return false;
518*042d53a7SEvalZero }
519*042d53a7SEvalZero
520*042d53a7SEvalZero sub->kr_flag = new_kr;
521*042d53a7SEvalZero
522*042d53a7SEvalZero if (sub->kr_flag) {
523*042d53a7SEvalZero if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
524*042d53a7SEvalZero BT_DBG("Phase 1 -> Phase 2");
525*042d53a7SEvalZero sub->kr_phase = BT_MESH_KR_PHASE_2;
526*042d53a7SEvalZero return true;
527*042d53a7SEvalZero }
528*042d53a7SEvalZero } else {
529*042d53a7SEvalZero switch (sub->kr_phase) {
530*042d53a7SEvalZero case BT_MESH_KR_PHASE_1:
531*042d53a7SEvalZero if (!new_key) {
532*042d53a7SEvalZero /* Ignore */
533*042d53a7SEvalZero break;
534*042d53a7SEvalZero }
535*042d53a7SEvalZero /* Upon receiving a Secure Network beacon with the KR flag set
536*042d53a7SEvalZero * to 0 using the new NetKey in Phase 1, the node shall
537*042d53a7SEvalZero * immediately transition to Phase 3, which effectively skips
538*042d53a7SEvalZero * Phase 2.
539*042d53a7SEvalZero *
540*042d53a7SEvalZero * Intentional fall-through.
541*042d53a7SEvalZero */
542*042d53a7SEvalZero case BT_MESH_KR_PHASE_2:
543*042d53a7SEvalZero BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase);
544*042d53a7SEvalZero bt_mesh_net_revoke_keys(sub);
545*042d53a7SEvalZero if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
546*042d53a7SEvalZero (MYNEWT_VAL(BLE_MESH_FRIEND))) {
547*042d53a7SEvalZero friend_cred_refresh(sub->net_idx);
548*042d53a7SEvalZero }
549*042d53a7SEvalZero sub->kr_phase = BT_MESH_KR_NORMAL;
550*042d53a7SEvalZero return true;
551*042d53a7SEvalZero }
552*042d53a7SEvalZero }
553*042d53a7SEvalZero
554*042d53a7SEvalZero return false;
555*042d53a7SEvalZero }
556*042d53a7SEvalZero
bt_mesh_rpl_reset(void)557*042d53a7SEvalZero void bt_mesh_rpl_reset(void)
558*042d53a7SEvalZero {
559*042d53a7SEvalZero int i;
560*042d53a7SEvalZero
561*042d53a7SEvalZero /* Discard "old old" IV Index entries from RPL and flag
562*042d53a7SEvalZero * any other ones (which are valid) as old.
563*042d53a7SEvalZero */
564*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
565*042d53a7SEvalZero struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
566*042d53a7SEvalZero
567*042d53a7SEvalZero if (rpl->src) {
568*042d53a7SEvalZero if (rpl->old_iv) {
569*042d53a7SEvalZero memset(rpl, 0, sizeof(*rpl));
570*042d53a7SEvalZero } else {
571*042d53a7SEvalZero rpl->old_iv = true;
572*042d53a7SEvalZero }
573*042d53a7SEvalZero }
574*042d53a7SEvalZero }
575*042d53a7SEvalZero }
576*042d53a7SEvalZero
577*042d53a7SEvalZero #if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
bt_mesh_iv_update_test(bool enable)578*042d53a7SEvalZero void bt_mesh_iv_update_test(bool enable)
579*042d53a7SEvalZero {
580*042d53a7SEvalZero bt_mesh.ivu_test = enable;
581*042d53a7SEvalZero /* Reset the duration variable - needed for some PTS tests */
582*042d53a7SEvalZero bt_mesh.ivu_duration = 0;
583*042d53a7SEvalZero }
584*042d53a7SEvalZero
bt_mesh_iv_update(void)585*042d53a7SEvalZero bool bt_mesh_iv_update(void)
586*042d53a7SEvalZero {
587*042d53a7SEvalZero if (!bt_mesh_is_provisioned()) {
588*042d53a7SEvalZero BT_ERR("Not yet provisioned");
589*042d53a7SEvalZero return false;
590*042d53a7SEvalZero }
591*042d53a7SEvalZero
592*042d53a7SEvalZero if (bt_mesh.iv_update) {
593*042d53a7SEvalZero bt_mesh_net_iv_update(bt_mesh.iv_index, false);
594*042d53a7SEvalZero } else {
595*042d53a7SEvalZero bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
596*042d53a7SEvalZero }
597*042d53a7SEvalZero
598*042d53a7SEvalZero bt_mesh_net_sec_update(NULL);
599*042d53a7SEvalZero
600*042d53a7SEvalZero return bt_mesh.iv_update;
601*042d53a7SEvalZero }
602*042d53a7SEvalZero #endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
603*042d53a7SEvalZero
604*042d53a7SEvalZero /* Used for sending immediate beacons to Friend queues and GATT clients */
bt_mesh_net_sec_update(struct bt_mesh_subnet * sub)605*042d53a7SEvalZero void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
606*042d53a7SEvalZero {
607*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
608*042d53a7SEvalZero bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
609*042d53a7SEvalZero }
610*042d53a7SEvalZero
611*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
612*042d53a7SEvalZero bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
613*042d53a7SEvalZero bt_mesh_proxy_beacon_send(sub);
614*042d53a7SEvalZero }
615*042d53a7SEvalZero }
616*042d53a7SEvalZero
bt_mesh_net_iv_update(u32_t iv_index,bool iv_update)617*042d53a7SEvalZero bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
618*042d53a7SEvalZero {
619*042d53a7SEvalZero int i;
620*042d53a7SEvalZero
621*042d53a7SEvalZero if (bt_mesh.iv_update) {
622*042d53a7SEvalZero /* We're currently in IV Update mode */
623*042d53a7SEvalZero
624*042d53a7SEvalZero if (iv_index != bt_mesh.iv_index) {
625*042d53a7SEvalZero BT_WARN("IV Index mismatch: 0x%08x != 0x%08x",
626*042d53a7SEvalZero iv_index, bt_mesh.iv_index);
627*042d53a7SEvalZero return false;
628*042d53a7SEvalZero }
629*042d53a7SEvalZero
630*042d53a7SEvalZero if (iv_update) {
631*042d53a7SEvalZero /* Nothing to do */
632*042d53a7SEvalZero BT_DBG("Already in IV Update in Progress state");
633*042d53a7SEvalZero return false;
634*042d53a7SEvalZero }
635*042d53a7SEvalZero } else {
636*042d53a7SEvalZero /* We're currently in Normal mode */
637*042d53a7SEvalZero
638*042d53a7SEvalZero if (iv_index == bt_mesh.iv_index) {
639*042d53a7SEvalZero BT_DBG("Same IV Index in normal mode");
640*042d53a7SEvalZero return false;
641*042d53a7SEvalZero }
642*042d53a7SEvalZero
643*042d53a7SEvalZero if (iv_index < bt_mesh.iv_index ||
644*042d53a7SEvalZero iv_index > bt_mesh.iv_index + 42) {
645*042d53a7SEvalZero BT_ERR("IV Index out of sync: 0x%08x != 0x%08x",
646*042d53a7SEvalZero iv_index, bt_mesh.iv_index);
647*042d53a7SEvalZero return false;
648*042d53a7SEvalZero }
649*042d53a7SEvalZero
650*042d53a7SEvalZero if (iv_index > bt_mesh.iv_index + 1) {
651*042d53a7SEvalZero BT_WARN("Performing IV Index Recovery");
652*042d53a7SEvalZero memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
653*042d53a7SEvalZero bt_mesh.iv_index = iv_index;
654*042d53a7SEvalZero bt_mesh.seq = 0;
655*042d53a7SEvalZero goto do_update;
656*042d53a7SEvalZero }
657*042d53a7SEvalZero
658*042d53a7SEvalZero if (iv_index == bt_mesh.iv_index + 1 && !iv_update) {
659*042d53a7SEvalZero BT_WARN("Ignoring new index in normal mode");
660*042d53a7SEvalZero return false;
661*042d53a7SEvalZero }
662*042d53a7SEvalZero
663*042d53a7SEvalZero if (!iv_update) {
664*042d53a7SEvalZero /* Nothing to do */
665*042d53a7SEvalZero BT_DBG("Already in Normal state");
666*042d53a7SEvalZero return false;
667*042d53a7SEvalZero }
668*042d53a7SEvalZero }
669*042d53a7SEvalZero
670*042d53a7SEvalZero if (!(IS_ENABLED(CONFIG_BT_MESH_IV_UPDATE_TEST) && bt_mesh.ivu_test)) {
671*042d53a7SEvalZero if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
672*042d53a7SEvalZero BT_WARN("IV Update before minimum duration");
673*042d53a7SEvalZero return false;
674*042d53a7SEvalZero }
675*042d53a7SEvalZero }
676*042d53a7SEvalZero
677*042d53a7SEvalZero /* Defer change to Normal Operation if there are pending acks */
678*042d53a7SEvalZero if (!iv_update && bt_mesh_tx_in_progress()) {
679*042d53a7SEvalZero BT_WARN("IV Update deferred because of pending transfer");
680*042d53a7SEvalZero bt_mesh.pending_update = 1;
681*042d53a7SEvalZero return false;
682*042d53a7SEvalZero }
683*042d53a7SEvalZero
684*042d53a7SEvalZero do_update:
685*042d53a7SEvalZero bt_mesh.iv_update = iv_update;
686*042d53a7SEvalZero bt_mesh.ivu_duration = 0;
687*042d53a7SEvalZero
688*042d53a7SEvalZero if (bt_mesh.iv_update) {
689*042d53a7SEvalZero bt_mesh.iv_index = iv_index;
690*042d53a7SEvalZero BT_DBG("IV Update state entered. New index 0x%08x",
691*042d53a7SEvalZero bt_mesh.iv_index);
692*042d53a7SEvalZero
693*042d53a7SEvalZero bt_mesh_rpl_reset();
694*042d53a7SEvalZero } else {
695*042d53a7SEvalZero BT_DBG("Normal mode entered");
696*042d53a7SEvalZero bt_mesh.seq = 0;
697*042d53a7SEvalZero }
698*042d53a7SEvalZero
699*042d53a7SEvalZero k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
700*042d53a7SEvalZero
701*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
702*042d53a7SEvalZero if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
703*042d53a7SEvalZero bt_mesh_net_beacon_update(&bt_mesh.sub[i]);
704*042d53a7SEvalZero }
705*042d53a7SEvalZero }
706*042d53a7SEvalZero
707*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
708*042d53a7SEvalZero bt_mesh_store_iv(false);
709*042d53a7SEvalZero }
710*042d53a7SEvalZero
711*042d53a7SEvalZero return true;
712*042d53a7SEvalZero }
713*042d53a7SEvalZero
bt_mesh_next_seq(void)714*042d53a7SEvalZero u32_t bt_mesh_next_seq(void)
715*042d53a7SEvalZero {
716*042d53a7SEvalZero u32_t seq = bt_mesh.seq++;
717*042d53a7SEvalZero
718*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
719*042d53a7SEvalZero bt_mesh_store_seq();
720*042d53a7SEvalZero }
721*042d53a7SEvalZero
722*042d53a7SEvalZero return seq;
723*042d53a7SEvalZero }
724*042d53a7SEvalZero
bt_mesh_net_resend(struct bt_mesh_subnet * sub,struct os_mbuf * buf,bool new_key,const struct bt_mesh_send_cb * cb,void * cb_data)725*042d53a7SEvalZero int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
726*042d53a7SEvalZero bool new_key, const struct bt_mesh_send_cb *cb,
727*042d53a7SEvalZero void *cb_data)
728*042d53a7SEvalZero {
729*042d53a7SEvalZero const u8_t *enc, *priv;
730*042d53a7SEvalZero u32_t seq;
731*042d53a7SEvalZero int err;
732*042d53a7SEvalZero
733*042d53a7SEvalZero BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
734*042d53a7SEvalZero buf->om_len);
735*042d53a7SEvalZero
736*042d53a7SEvalZero enc = sub->keys[new_key].enc;
737*042d53a7SEvalZero priv = sub->keys[new_key].privacy;
738*042d53a7SEvalZero
739*042d53a7SEvalZero err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
740*042d53a7SEvalZero if (err) {
741*042d53a7SEvalZero BT_ERR("deobfuscate failed (err %d)", err);
742*042d53a7SEvalZero return err;
743*042d53a7SEvalZero }
744*042d53a7SEvalZero
745*042d53a7SEvalZero err = bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
746*042d53a7SEvalZero if (err) {
747*042d53a7SEvalZero BT_ERR("decrypt failed (err %d)", err);
748*042d53a7SEvalZero return err;
749*042d53a7SEvalZero }
750*042d53a7SEvalZero
751*042d53a7SEvalZero seq = bt_mesh_next_seq();
752*042d53a7SEvalZero buf->om_data[2] = seq >> 16;
753*042d53a7SEvalZero buf->om_data[3] = seq >> 8;
754*042d53a7SEvalZero buf->om_data[4] = seq;
755*042d53a7SEvalZero
756*042d53a7SEvalZero err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
757*042d53a7SEvalZero if (err) {
758*042d53a7SEvalZero BT_ERR("encrypt failed (err %d)", err);
759*042d53a7SEvalZero return err;
760*042d53a7SEvalZero }
761*042d53a7SEvalZero
762*042d53a7SEvalZero err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
763*042d53a7SEvalZero if (err) {
764*042d53a7SEvalZero BT_ERR("obfuscate failed (err %d)", err);
765*042d53a7SEvalZero return err;
766*042d53a7SEvalZero }
767*042d53a7SEvalZero
768*042d53a7SEvalZero bt_mesh_adv_send(buf, cb, cb_data);
769*042d53a7SEvalZero
770*042d53a7SEvalZero if (!bt_mesh.iv_update && bt_mesh.seq > IV_UPDATE_SEQ_LIMIT) {
771*042d53a7SEvalZero bt_mesh_beacon_ivu_initiator(true);
772*042d53a7SEvalZero bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
773*042d53a7SEvalZero bt_mesh_net_sec_update(NULL);
774*042d53a7SEvalZero }
775*042d53a7SEvalZero
776*042d53a7SEvalZero return 0;
777*042d53a7SEvalZero }
778*042d53a7SEvalZero
bt_mesh_net_local(struct ble_npl_event * work)779*042d53a7SEvalZero static void bt_mesh_net_local(struct ble_npl_event *work)
780*042d53a7SEvalZero {
781*042d53a7SEvalZero struct os_mbuf *buf;
782*042d53a7SEvalZero
783*042d53a7SEvalZero while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
784*042d53a7SEvalZero BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
785*042d53a7SEvalZero bt_mesh_net_recv(buf, 0, BT_MESH_NET_IF_LOCAL);
786*042d53a7SEvalZero net_buf_unref(buf);
787*042d53a7SEvalZero }
788*042d53a7SEvalZero }
789*042d53a7SEvalZero
bt_mesh_net_encode(struct bt_mesh_net_tx * tx,struct os_mbuf * buf,bool proxy)790*042d53a7SEvalZero int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
791*042d53a7SEvalZero bool proxy)
792*042d53a7SEvalZero {
793*042d53a7SEvalZero const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
794*042d53a7SEvalZero u32_t seq_val;
795*042d53a7SEvalZero u8_t nid;
796*042d53a7SEvalZero const u8_t *enc, *priv;
797*042d53a7SEvalZero u8_t *seq;
798*042d53a7SEvalZero int err;
799*042d53a7SEvalZero
800*042d53a7SEvalZero if (ctl && net_buf_simple_tailroom(buf) < 8) {
801*042d53a7SEvalZero BT_ERR("Insufficient MIC space for CTL PDU");
802*042d53a7SEvalZero return -EINVAL;
803*042d53a7SEvalZero } else if (net_buf_simple_tailroom(buf) < 4) {
804*042d53a7SEvalZero BT_ERR("Insufficient MIC space for PDU");
805*042d53a7SEvalZero return -EINVAL;
806*042d53a7SEvalZero }
807*042d53a7SEvalZero
808*042d53a7SEvalZero BT_DBG("src 0x%04x dst 0x%04x ctl %u seq 0x%06x",
809*042d53a7SEvalZero tx->src, tx->ctx->addr, ctl, bt_mesh.seq);
810*042d53a7SEvalZero
811*042d53a7SEvalZero net_buf_simple_push_be16(buf, tx->ctx->addr);
812*042d53a7SEvalZero net_buf_simple_push_be16(buf, tx->src);
813*042d53a7SEvalZero
814*042d53a7SEvalZero seq = net_buf_simple_push(buf, 3);
815*042d53a7SEvalZero seq_val = bt_mesh_next_seq();
816*042d53a7SEvalZero seq[0] = seq_val >> 16;
817*042d53a7SEvalZero seq[1] = seq_val >> 8;
818*042d53a7SEvalZero seq[2] = seq_val;
819*042d53a7SEvalZero
820*042d53a7SEvalZero if (ctl) {
821*042d53a7SEvalZero net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80);
822*042d53a7SEvalZero } else {
823*042d53a7SEvalZero net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
824*042d53a7SEvalZero }
825*042d53a7SEvalZero
826*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) {
827*042d53a7SEvalZero if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED,
828*042d53a7SEvalZero &nid, &enc, &priv)) {
829*042d53a7SEvalZero BT_WARN("Falling back to master credentials");
830*042d53a7SEvalZero
831*042d53a7SEvalZero tx->friend_cred = 0;
832*042d53a7SEvalZero
833*042d53a7SEvalZero nid = tx->sub->keys[tx->sub->kr_flag].nid;
834*042d53a7SEvalZero enc = tx->sub->keys[tx->sub->kr_flag].enc;
835*042d53a7SEvalZero priv = tx->sub->keys[tx->sub->kr_flag].privacy;
836*042d53a7SEvalZero }
837*042d53a7SEvalZero } else {
838*042d53a7SEvalZero tx->friend_cred = 0;
839*042d53a7SEvalZero nid = tx->sub->keys[tx->sub->kr_flag].nid;
840*042d53a7SEvalZero enc = tx->sub->keys[tx->sub->kr_flag].enc;
841*042d53a7SEvalZero priv = tx->sub->keys[tx->sub->kr_flag].privacy;
842*042d53a7SEvalZero }
843*042d53a7SEvalZero
844*042d53a7SEvalZero net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
845*042d53a7SEvalZero
846*042d53a7SEvalZero err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy);
847*042d53a7SEvalZero if (err) {
848*042d53a7SEvalZero return err;
849*042d53a7SEvalZero }
850*042d53a7SEvalZero
851*042d53a7SEvalZero return bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
852*042d53a7SEvalZero }
853*042d53a7SEvalZero
bt_mesh_net_send(struct bt_mesh_net_tx * tx,struct os_mbuf * buf,const struct bt_mesh_send_cb * cb,void * cb_data)854*042d53a7SEvalZero int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
855*042d53a7SEvalZero const struct bt_mesh_send_cb *cb, void *cb_data)
856*042d53a7SEvalZero {
857*042d53a7SEvalZero int err;
858*042d53a7SEvalZero
859*042d53a7SEvalZero BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
860*042d53a7SEvalZero tx->src, tx->ctx->addr, buf->om_len, net_buf_headroom(buf),
861*042d53a7SEvalZero net_buf_tailroom(buf));
862*042d53a7SEvalZero BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
863*042d53a7SEvalZero BT_DBG("Seq 0x%06x", bt_mesh.seq);
864*042d53a7SEvalZero
865*042d53a7SEvalZero if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
866*042d53a7SEvalZero tx->ctx->send_ttl = bt_mesh_default_ttl_get();
867*042d53a7SEvalZero }
868*042d53a7SEvalZero
869*042d53a7SEvalZero err = bt_mesh_net_encode(tx, buf, false);
870*042d53a7SEvalZero if (err) {
871*042d53a7SEvalZero goto done;
872*042d53a7SEvalZero }
873*042d53a7SEvalZero
874*042d53a7SEvalZero BT_DBG("encoded %u bytes: %s", buf->om_len,
875*042d53a7SEvalZero bt_hex(buf->om_data, buf->om_len));
876*042d53a7SEvalZero
877*042d53a7SEvalZero /* Deliver to GATT Proxy Clients if necessary. Mesh spec 3.4.5.2:
878*042d53a7SEvalZero * "The output filter of the interface connected to advertising or
879*042d53a7SEvalZero * GATT bearers shall drop all messages with TTL value set to 1."
880*042d53a7SEvalZero */
881*042d53a7SEvalZero if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) &&
882*042d53a7SEvalZero tx->ctx->send_ttl != 1) {
883*042d53a7SEvalZero if (bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
884*042d53a7SEvalZero BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
885*042d53a7SEvalZero /* Notify completion if this only went
886*042d53a7SEvalZero * through the Mesh Proxy.
887*042d53a7SEvalZero */
888*042d53a7SEvalZero if (cb) {
889*042d53a7SEvalZero if (cb->start) {
890*042d53a7SEvalZero cb->start(0, 0, cb_data);
891*042d53a7SEvalZero }
892*042d53a7SEvalZero
893*042d53a7SEvalZero if (cb->end) {
894*042d53a7SEvalZero cb->end(0, cb_data);
895*042d53a7SEvalZero }
896*042d53a7SEvalZero }
897*042d53a7SEvalZero
898*042d53a7SEvalZero err = 0;
899*042d53a7SEvalZero goto done;
900*042d53a7SEvalZero }
901*042d53a7SEvalZero }
902*042d53a7SEvalZero
903*042d53a7SEvalZero /* Deliver to local network interface if necessary */
904*042d53a7SEvalZero if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
905*042d53a7SEvalZero bt_mesh_elem_find(tx->ctx->addr)) {
906*042d53a7SEvalZero if (cb && cb->start) {
907*042d53a7SEvalZero cb->start(0, 0, cb_data);
908*042d53a7SEvalZero }
909*042d53a7SEvalZero net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
910*042d53a7SEvalZero if (cb && cb->end) {
911*042d53a7SEvalZero cb->end(0, cb_data);
912*042d53a7SEvalZero }
913*042d53a7SEvalZero k_work_submit(&bt_mesh.local_work);
914*042d53a7SEvalZero } else if (tx->ctx->send_ttl != 1) {
915*042d53a7SEvalZero /* Deliver to to the advertising network interface. Mesh spec
916*042d53a7SEvalZero * 3.4.5.2: "The output filter of the interface connected to
917*042d53a7SEvalZero * advertising or GATT bearers shall drop all messages with
918*042d53a7SEvalZero * TTL value set to 1."
919*042d53a7SEvalZero */
920*042d53a7SEvalZero bt_mesh_adv_send(buf, cb, cb_data);
921*042d53a7SEvalZero }
922*042d53a7SEvalZero
923*042d53a7SEvalZero done:
924*042d53a7SEvalZero net_buf_unref(buf);
925*042d53a7SEvalZero return err;
926*042d53a7SEvalZero }
927*042d53a7SEvalZero
auth_match(struct bt_mesh_subnet_keys * keys,const u8_t net_id[8],u8_t flags,u32_t iv_index,const u8_t auth[8])928*042d53a7SEvalZero static bool auth_match(struct bt_mesh_subnet_keys *keys,
929*042d53a7SEvalZero const u8_t net_id[8], u8_t flags,
930*042d53a7SEvalZero u32_t iv_index, const u8_t auth[8])
931*042d53a7SEvalZero {
932*042d53a7SEvalZero u8_t net_auth[8];
933*042d53a7SEvalZero
934*042d53a7SEvalZero if (memcmp(net_id, keys->net_id, 8)) {
935*042d53a7SEvalZero return false;
936*042d53a7SEvalZero }
937*042d53a7SEvalZero
938*042d53a7SEvalZero bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index,
939*042d53a7SEvalZero net_auth);
940*042d53a7SEvalZero
941*042d53a7SEvalZero if (memcmp(auth, net_auth, 8)) {
942*042d53a7SEvalZero BT_WARN("Authentication Value %s != %s",
943*042d53a7SEvalZero bt_hex(auth, 8), bt_hex(net_auth, 8));
944*042d53a7SEvalZero return false;
945*042d53a7SEvalZero }
946*042d53a7SEvalZero
947*042d53a7SEvalZero return true;
948*042d53a7SEvalZero }
949*042d53a7SEvalZero
bt_mesh_subnet_find(const u8_t net_id[8],u8_t flags,u32_t iv_index,const u8_t auth[8],bool * new_key)950*042d53a7SEvalZero struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
951*042d53a7SEvalZero u32_t iv_index, const u8_t auth[8],
952*042d53a7SEvalZero bool *new_key)
953*042d53a7SEvalZero {
954*042d53a7SEvalZero int i;
955*042d53a7SEvalZero
956*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
957*042d53a7SEvalZero struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
958*042d53a7SEvalZero
959*042d53a7SEvalZero if (sub->net_idx == BT_MESH_KEY_UNUSED) {
960*042d53a7SEvalZero continue;
961*042d53a7SEvalZero }
962*042d53a7SEvalZero
963*042d53a7SEvalZero if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) {
964*042d53a7SEvalZero *new_key = false;
965*042d53a7SEvalZero return sub;
966*042d53a7SEvalZero }
967*042d53a7SEvalZero
968*042d53a7SEvalZero if (sub->kr_phase == BT_MESH_KR_NORMAL) {
969*042d53a7SEvalZero continue;
970*042d53a7SEvalZero }
971*042d53a7SEvalZero
972*042d53a7SEvalZero if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) {
973*042d53a7SEvalZero *new_key = true;
974*042d53a7SEvalZero return sub;
975*042d53a7SEvalZero }
976*042d53a7SEvalZero }
977*042d53a7SEvalZero
978*042d53a7SEvalZero return NULL;
979*042d53a7SEvalZero }
980*042d53a7SEvalZero
net_decrypt(struct bt_mesh_subnet * sub,const u8_t * enc,const u8_t * priv,const u8_t * data,size_t data_len,struct bt_mesh_net_rx * rx,struct os_mbuf * buf)981*042d53a7SEvalZero static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
982*042d53a7SEvalZero const u8_t *priv, const u8_t *data,
983*042d53a7SEvalZero size_t data_len, struct bt_mesh_net_rx *rx,
984*042d53a7SEvalZero struct os_mbuf *buf)
985*042d53a7SEvalZero {
986*042d53a7SEvalZero BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
987*042d53a7SEvalZero BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data), bt_mesh.iv_index);
988*042d53a7SEvalZero
989*042d53a7SEvalZero rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01));
990*042d53a7SEvalZero
991*042d53a7SEvalZero net_buf_simple_init(buf, 0);
992*042d53a7SEvalZero memcpy(net_buf_simple_add(buf, data_len), data, data_len);
993*042d53a7SEvalZero
994*042d53a7SEvalZero if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
995*042d53a7SEvalZero return -ENOENT;
996*042d53a7SEvalZero }
997*042d53a7SEvalZero
998*042d53a7SEvalZero if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
999*042d53a7SEvalZero BT_WARN("Duplicate found in Network Message Cache");
1000*042d53a7SEvalZero return -EALREADY;
1001*042d53a7SEvalZero }
1002*042d53a7SEvalZero
1003*042d53a7SEvalZero rx->ctx.addr = SRC(buf->om_data);
1004*042d53a7SEvalZero if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) {
1005*042d53a7SEvalZero BT_WARN("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
1006*042d53a7SEvalZero return -EINVAL;
1007*042d53a7SEvalZero }
1008*042d53a7SEvalZero
1009*042d53a7SEvalZero BT_DBG("src 0x%04x", rx->ctx.addr);
1010*042d53a7SEvalZero
1011*042d53a7SEvalZero if ((MYNEWT_VAL(BLE_MESH_PROXY)) &&
1012*042d53a7SEvalZero rx->net_if == BT_MESH_NET_IF_PROXY_CFG) {
1013*042d53a7SEvalZero return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx),
1014*042d53a7SEvalZero true);
1015*042d53a7SEvalZero }
1016*042d53a7SEvalZero
1017*042d53a7SEvalZero return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
1018*042d53a7SEvalZero }
1019*042d53a7SEvalZero
1020*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_MESH_LOW_POWER) || \
1021*042d53a7SEvalZero MYNEWT_VAL(BLE_MESH_FRIEND))
friend_decrypt(struct bt_mesh_subnet * sub,const u8_t * data,size_t data_len,struct bt_mesh_net_rx * rx,struct os_mbuf * buf)1022*042d53a7SEvalZero static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
1023*042d53a7SEvalZero size_t data_len, struct bt_mesh_net_rx *rx,
1024*042d53a7SEvalZero struct os_mbuf *buf)
1025*042d53a7SEvalZero {
1026*042d53a7SEvalZero int i;
1027*042d53a7SEvalZero
1028*042d53a7SEvalZero BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
1029*042d53a7SEvalZero
1030*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
1031*042d53a7SEvalZero struct friend_cred *cred = &friend_cred[i];
1032*042d53a7SEvalZero
1033*042d53a7SEvalZero if (cred->net_idx != sub->net_idx) {
1034*042d53a7SEvalZero continue;
1035*042d53a7SEvalZero }
1036*042d53a7SEvalZero
1037*042d53a7SEvalZero if (NID(data) == cred->cred[0].nid &&
1038*042d53a7SEvalZero !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy,
1039*042d53a7SEvalZero data, data_len, rx, buf)) {
1040*042d53a7SEvalZero return 0;
1041*042d53a7SEvalZero }
1042*042d53a7SEvalZero
1043*042d53a7SEvalZero if (sub->kr_phase == BT_MESH_KR_NORMAL) {
1044*042d53a7SEvalZero continue;
1045*042d53a7SEvalZero }
1046*042d53a7SEvalZero
1047*042d53a7SEvalZero if (NID(data) == cred->cred[1].nid &&
1048*042d53a7SEvalZero !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy,
1049*042d53a7SEvalZero data, data_len, rx, buf)) {
1050*042d53a7SEvalZero rx->new_key = 1;
1051*042d53a7SEvalZero return 0;
1052*042d53a7SEvalZero }
1053*042d53a7SEvalZero }
1054*042d53a7SEvalZero
1055*042d53a7SEvalZero return -ENOENT;
1056*042d53a7SEvalZero }
1057*042d53a7SEvalZero #endif
1058*042d53a7SEvalZero
net_find_and_decrypt(const u8_t * data,size_t data_len,struct bt_mesh_net_rx * rx,struct os_mbuf * buf)1059*042d53a7SEvalZero static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
1060*042d53a7SEvalZero struct bt_mesh_net_rx *rx,
1061*042d53a7SEvalZero struct os_mbuf *buf)
1062*042d53a7SEvalZero {
1063*042d53a7SEvalZero struct bt_mesh_subnet *sub;
1064*042d53a7SEvalZero unsigned int i;
1065*042d53a7SEvalZero
1066*042d53a7SEvalZero BT_DBG("");
1067*042d53a7SEvalZero
1068*042d53a7SEvalZero for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
1069*042d53a7SEvalZero sub = &bt_mesh.sub[i];
1070*042d53a7SEvalZero if (sub->net_idx == BT_MESH_KEY_UNUSED) {
1071*042d53a7SEvalZero continue;
1072*042d53a7SEvalZero }
1073*042d53a7SEvalZero
1074*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_MESH_LOW_POWER) || \
1075*042d53a7SEvalZero MYNEWT_VAL(BLE_MESH_FRIEND))
1076*042d53a7SEvalZero if (!friend_decrypt(sub, data, data_len, rx, buf)) {
1077*042d53a7SEvalZero rx->friend_cred = 1;
1078*042d53a7SEvalZero rx->ctx.net_idx = sub->net_idx;
1079*042d53a7SEvalZero rx->sub = sub;
1080*042d53a7SEvalZero return true;
1081*042d53a7SEvalZero }
1082*042d53a7SEvalZero #endif
1083*042d53a7SEvalZero
1084*042d53a7SEvalZero if (NID(data) == sub->keys[0].nid &&
1085*042d53a7SEvalZero !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
1086*042d53a7SEvalZero data, data_len, rx, buf)) {
1087*042d53a7SEvalZero rx->ctx.net_idx = sub->net_idx;
1088*042d53a7SEvalZero rx->sub = sub;
1089*042d53a7SEvalZero return true;
1090*042d53a7SEvalZero }
1091*042d53a7SEvalZero
1092*042d53a7SEvalZero if (sub->kr_phase == BT_MESH_KR_NORMAL) {
1093*042d53a7SEvalZero continue;
1094*042d53a7SEvalZero }
1095*042d53a7SEvalZero
1096*042d53a7SEvalZero if (NID(data) == sub->keys[1].nid &&
1097*042d53a7SEvalZero !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy,
1098*042d53a7SEvalZero data, data_len, rx, buf)) {
1099*042d53a7SEvalZero rx->new_key = 1;
1100*042d53a7SEvalZero rx->ctx.net_idx = sub->net_idx;
1101*042d53a7SEvalZero rx->sub = sub;
1102*042d53a7SEvalZero return true;
1103*042d53a7SEvalZero }
1104*042d53a7SEvalZero }
1105*042d53a7SEvalZero
1106*042d53a7SEvalZero return false;
1107*042d53a7SEvalZero }
1108*042d53a7SEvalZero
1109*042d53a7SEvalZero /* Relaying from advertising to the advertising bearer should only happen
1110*042d53a7SEvalZero * if the Relay state is set to enabled. Locally originated packets always
1111*042d53a7SEvalZero * get sent to the advertising bearer. If the packet came in through GATT,
1112*042d53a7SEvalZero * then we should only relay it if the GATT Proxy state is enabled.
1113*042d53a7SEvalZero */
relay_to_adv(enum bt_mesh_net_if net_if)1114*042d53a7SEvalZero static bool relay_to_adv(enum bt_mesh_net_if net_if)
1115*042d53a7SEvalZero {
1116*042d53a7SEvalZero switch (net_if) {
1117*042d53a7SEvalZero case BT_MESH_NET_IF_LOCAL:
1118*042d53a7SEvalZero return true;
1119*042d53a7SEvalZero case BT_MESH_NET_IF_ADV:
1120*042d53a7SEvalZero return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
1121*042d53a7SEvalZero case BT_MESH_NET_IF_PROXY:
1122*042d53a7SEvalZero return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
1123*042d53a7SEvalZero default:
1124*042d53a7SEvalZero return false;
1125*042d53a7SEvalZero }
1126*042d53a7SEvalZero }
1127*042d53a7SEvalZero
bt_mesh_net_relay(struct os_mbuf * sbuf,struct bt_mesh_net_rx * rx)1128*042d53a7SEvalZero static void bt_mesh_net_relay(struct os_mbuf *sbuf,
1129*042d53a7SEvalZero struct bt_mesh_net_rx *rx)
1130*042d53a7SEvalZero {
1131*042d53a7SEvalZero const u8_t *enc, *priv;
1132*042d53a7SEvalZero struct os_mbuf *buf;
1133*042d53a7SEvalZero u8_t nid, transmit;
1134*042d53a7SEvalZero
1135*042d53a7SEvalZero if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
1136*042d53a7SEvalZero /* Locally originated PDUs with TTL=1 will only be delivered
1137*042d53a7SEvalZero * to local elements as per Mesh Profile 1.0 section 3.4.5.2:
1138*042d53a7SEvalZero * "The output filter of the interface connected to
1139*042d53a7SEvalZero * advertising or GATT bearers shall drop all messages with
1140*042d53a7SEvalZero * TTL value set to 1."
1141*042d53a7SEvalZero */
1142*042d53a7SEvalZero if (rx->ctx.recv_ttl == 1) {
1143*042d53a7SEvalZero return;
1144*042d53a7SEvalZero }
1145*042d53a7SEvalZero } else {
1146*042d53a7SEvalZero if (rx->ctx.recv_ttl <= 1) {
1147*042d53a7SEvalZero return;
1148*042d53a7SEvalZero }
1149*042d53a7SEvalZero }
1150*042d53a7SEvalZero
1151*042d53a7SEvalZero if (rx->net_if == BT_MESH_NET_IF_ADV &&
1152*042d53a7SEvalZero bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED &&
1153*042d53a7SEvalZero bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) {
1154*042d53a7SEvalZero return;
1155*042d53a7SEvalZero }
1156*042d53a7SEvalZero
1157*042d53a7SEvalZero BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl,
1158*042d53a7SEvalZero rx->ctx.recv_dst);
1159*042d53a7SEvalZero
1160*042d53a7SEvalZero /* The Relay Retransmit state is only applied to adv-adv relaying.
1161*042d53a7SEvalZero * Anything else (like GATT to adv, or locally originated packets)
1162*042d53a7SEvalZero * use the Network Transmit state.
1163*042d53a7SEvalZero */
1164*042d53a7SEvalZero if (rx->net_if == BT_MESH_NET_IF_ADV) {
1165*042d53a7SEvalZero transmit = bt_mesh_relay_retransmit_get();
1166*042d53a7SEvalZero } else {
1167*042d53a7SEvalZero transmit = bt_mesh_net_transmit_get();
1168*042d53a7SEvalZero }
1169*042d53a7SEvalZero
1170*042d53a7SEvalZero buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, transmit, K_NO_WAIT);
1171*042d53a7SEvalZero if (!buf) {
1172*042d53a7SEvalZero BT_ERR("Out of relay buffers");
1173*042d53a7SEvalZero return;
1174*042d53a7SEvalZero }
1175*042d53a7SEvalZero
1176*042d53a7SEvalZero /* Only decrement TTL for non-locally originated packets */
1177*042d53a7SEvalZero if (rx->net_if != BT_MESH_NET_IF_LOCAL) {
1178*042d53a7SEvalZero /* Leave CTL bit intact */
1179*042d53a7SEvalZero sbuf->om_data[1] &= 0x80;
1180*042d53a7SEvalZero sbuf->om_data[1] |= rx->ctx.recv_ttl - 1;
1181*042d53a7SEvalZero }
1182*042d53a7SEvalZero
1183*042d53a7SEvalZero net_buf_add_mem(buf, sbuf->om_data, sbuf->om_len);
1184*042d53a7SEvalZero
1185*042d53a7SEvalZero enc = rx->sub->keys[rx->sub->kr_flag].enc;
1186*042d53a7SEvalZero priv = rx->sub->keys[rx->sub->kr_flag].privacy;
1187*042d53a7SEvalZero nid = rx->sub->keys[rx->sub->kr_flag].nid;
1188*042d53a7SEvalZero
1189*042d53a7SEvalZero BT_DBG("Relaying packet. TTL is now %u", TTL(buf->om_data));
1190*042d53a7SEvalZero
1191*042d53a7SEvalZero /* Update NID if RX or RX was with friend credentials */
1192*042d53a7SEvalZero if (rx->friend_cred) {
1193*042d53a7SEvalZero buf->om_data[0] &= 0x80; /* Clear everything except IVI */
1194*042d53a7SEvalZero buf->om_data[0] |= nid;
1195*042d53a7SEvalZero }
1196*042d53a7SEvalZero
1197*042d53a7SEvalZero /* We re-encrypt and obfuscate using the received IVI rather than
1198*042d53a7SEvalZero * the normal TX IVI (which may be different) since the transport
1199*042d53a7SEvalZero * layer nonce includes the IVI.
1200*042d53a7SEvalZero */
1201*042d53a7SEvalZero if (bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false)) {
1202*042d53a7SEvalZero BT_ERR("Re-encrypting failed");
1203*042d53a7SEvalZero goto done;
1204*042d53a7SEvalZero }
1205*042d53a7SEvalZero
1206*042d53a7SEvalZero if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
1207*042d53a7SEvalZero BT_ERR("Re-obfuscating failed");
1208*042d53a7SEvalZero goto done;
1209*042d53a7SEvalZero }
1210*042d53a7SEvalZero
1211*042d53a7SEvalZero BT_DBG("encoded %u bytes: %s", buf->om_len,
1212*042d53a7SEvalZero bt_hex(buf->om_data, buf->om_len));
1213*042d53a7SEvalZero
1214*042d53a7SEvalZero /* Sending to the GATT bearer should only happen if GATT Proxy
1215*042d53a7SEvalZero * is enabled or the message originates from the local node.
1216*042d53a7SEvalZero */
1217*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
1218*042d53a7SEvalZero (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
1219*042d53a7SEvalZero rx->net_if == BT_MESH_NET_IF_LOCAL)) {
1220*042d53a7SEvalZero if (bt_mesh_proxy_relay(buf, rx->ctx.recv_dst) &&
1221*042d53a7SEvalZero BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
1222*042d53a7SEvalZero goto done;
1223*042d53a7SEvalZero }
1224*042d53a7SEvalZero }
1225*042d53a7SEvalZero
1226*042d53a7SEvalZero if (relay_to_adv(rx->net_if)) {
1227*042d53a7SEvalZero bt_mesh_adv_send(buf, NULL, NULL);
1228*042d53a7SEvalZero }
1229*042d53a7SEvalZero
1230*042d53a7SEvalZero done:
1231*042d53a7SEvalZero net_buf_unref(buf);
1232*042d53a7SEvalZero }
1233*042d53a7SEvalZero
bt_mesh_net_decode(struct os_mbuf * data,enum bt_mesh_net_if net_if,struct bt_mesh_net_rx * rx,struct os_mbuf * buf)1234*042d53a7SEvalZero int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
1235*042d53a7SEvalZero struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
1236*042d53a7SEvalZero {
1237*042d53a7SEvalZero if (data->om_len < BT_MESH_NET_MIN_PDU_LEN) {
1238*042d53a7SEvalZero BT_WARN("Dropping too short mesh packet (len %u)", data->om_len);
1239*042d53a7SEvalZero BT_WARN("%s", bt_hex(data->om_data, data->om_len));
1240*042d53a7SEvalZero return -EINVAL;
1241*042d53a7SEvalZero }
1242*042d53a7SEvalZero
1243*042d53a7SEvalZero if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) {
1244*042d53a7SEvalZero BT_DBG("duplicate packet; dropping %u bytes: %s", data->om_len,
1245*042d53a7SEvalZero bt_hex(data->om_data, data->om_len));
1246*042d53a7SEvalZero return -EINVAL;
1247*042d53a7SEvalZero }
1248*042d53a7SEvalZero
1249*042d53a7SEvalZero BT_DBG("%u bytes: %s", data->om_len, bt_hex(data->om_data, data->om_len));
1250*042d53a7SEvalZero
1251*042d53a7SEvalZero rx->net_if = net_if;
1252*042d53a7SEvalZero
1253*042d53a7SEvalZero if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) {
1254*042d53a7SEvalZero BT_DBG("Unable to find matching net for packet");
1255*042d53a7SEvalZero return -ENOENT;
1256*042d53a7SEvalZero }
1257*042d53a7SEvalZero
1258*042d53a7SEvalZero /* Initialize AppIdx to a sane value */
1259*042d53a7SEvalZero rx->ctx.app_idx = BT_MESH_KEY_UNUSED;
1260*042d53a7SEvalZero
1261*042d53a7SEvalZero rx->ctx.recv_ttl = TTL(buf->om_data);
1262*042d53a7SEvalZero
1263*042d53a7SEvalZero /* Default to responding with TTL 0 for non-routed messages */
1264*042d53a7SEvalZero if (rx->ctx.recv_ttl == 0) {
1265*042d53a7SEvalZero rx->ctx.send_ttl = 0;
1266*042d53a7SEvalZero } else {
1267*042d53a7SEvalZero rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT;
1268*042d53a7SEvalZero }
1269*042d53a7SEvalZero
1270*042d53a7SEvalZero rx->ctl = CTL(buf->om_data);
1271*042d53a7SEvalZero rx->seq = SEQ(buf->om_data);
1272*042d53a7SEvalZero rx->ctx.recv_dst = DST(buf->om_data);
1273*042d53a7SEvalZero
1274*042d53a7SEvalZero BT_DBG("Decryption successful. Payload len %u: %s", buf->om_len,
1275*042d53a7SEvalZero bt_hex(buf->om_data, buf->om_len));
1276*042d53a7SEvalZero
1277*042d53a7SEvalZero if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
1278*042d53a7SEvalZero rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
1279*042d53a7SEvalZero BT_ERR("Destination address is unassigned; dropping packet");
1280*042d53a7SEvalZero return -EBADMSG;
1281*042d53a7SEvalZero }
1282*042d53a7SEvalZero
1283*042d53a7SEvalZero if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) {
1284*042d53a7SEvalZero BT_ERR("Destination address is RFU; dropping packet");
1285*042d53a7SEvalZero return -EBADMSG;
1286*042d53a7SEvalZero }
1287*042d53a7SEvalZero
1288*042d53a7SEvalZero if (net_if != BT_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) {
1289*042d53a7SEvalZero BT_DBG("Dropping locally originated packet");
1290*042d53a7SEvalZero return -EBADMSG;
1291*042d53a7SEvalZero }
1292*042d53a7SEvalZero
1293*042d53a7SEvalZero BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
1294*042d53a7SEvalZero rx->ctx.recv_ttl);
1295*042d53a7SEvalZero BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len));
1296*042d53a7SEvalZero
1297*042d53a7SEvalZero return 0;
1298*042d53a7SEvalZero }
1299*042d53a7SEvalZero
bt_mesh_net_recv(struct os_mbuf * data,s8_t rssi,enum bt_mesh_net_if net_if)1300*042d53a7SEvalZero void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
1301*042d53a7SEvalZero enum bt_mesh_net_if net_if)
1302*042d53a7SEvalZero {
1303*042d53a7SEvalZero struct os_mbuf *buf = NET_BUF_SIMPLE(29);
1304*042d53a7SEvalZero struct bt_mesh_net_rx rx = { .rssi = rssi };
1305*042d53a7SEvalZero struct net_buf_simple_state state;
1306*042d53a7SEvalZero
1307*042d53a7SEvalZero BT_DBG("rssi %d net_if %u", rssi, net_if);
1308*042d53a7SEvalZero
1309*042d53a7SEvalZero if (!bt_mesh_is_provisioned()) {
1310*042d53a7SEvalZero BT_ERR("Not provisioned; dropping packet");
1311*042d53a7SEvalZero goto done;
1312*042d53a7SEvalZero }
1313*042d53a7SEvalZero
1314*042d53a7SEvalZero if (bt_mesh_net_decode(data, net_if, &rx, buf)) {
1315*042d53a7SEvalZero goto done;
1316*042d53a7SEvalZero }
1317*042d53a7SEvalZero
1318*042d53a7SEvalZero /* Save the state so the buffer can later be relayed */
1319*042d53a7SEvalZero net_buf_simple_save(buf, &state);
1320*042d53a7SEvalZero
1321*042d53a7SEvalZero if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY)) &&
1322*042d53a7SEvalZero net_if == BT_MESH_NET_IF_PROXY) {
1323*042d53a7SEvalZero bt_mesh_proxy_addr_add(data, rx.ctx.addr);
1324*042d53a7SEvalZero }
1325*042d53a7SEvalZero
1326*042d53a7SEvalZero rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) ||
1327*042d53a7SEvalZero bt_mesh_elem_find(rx.ctx.recv_dst));
1328*042d53a7SEvalZero
1329*042d53a7SEvalZero bt_mesh_trans_recv(buf, &rx);
1330*042d53a7SEvalZero
1331*042d53a7SEvalZero /* Relay if this was a group/virtual address, or if the destination
1332*042d53a7SEvalZero * was neither a local element nor an LPN we're Friends for.
1333*042d53a7SEvalZero */
1334*042d53a7SEvalZero if (!BT_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) ||
1335*042d53a7SEvalZero (!rx.local_match && !rx.friend_match)) {
1336*042d53a7SEvalZero net_buf_simple_restore(buf, &state);
1337*042d53a7SEvalZero bt_mesh_net_relay(buf, &rx);
1338*042d53a7SEvalZero }
1339*042d53a7SEvalZero
1340*042d53a7SEvalZero done:
1341*042d53a7SEvalZero os_mbuf_free_chain(buf);
1342*042d53a7SEvalZero }
1343*042d53a7SEvalZero
ivu_refresh(struct ble_npl_event * work)1344*042d53a7SEvalZero static void ivu_refresh(struct ble_npl_event *work)
1345*042d53a7SEvalZero {
1346*042d53a7SEvalZero bt_mesh.ivu_duration += BT_MESH_IVU_HOURS;
1347*042d53a7SEvalZero
1348*042d53a7SEvalZero BT_DBG("%s for %u hour%s",
1349*042d53a7SEvalZero bt_mesh.iv_update ? "IVU in Progress" : "IVU Normal mode",
1350*042d53a7SEvalZero bt_mesh.ivu_duration, bt_mesh.ivu_duration == 1 ? "" : "s");
1351*042d53a7SEvalZero
1352*042d53a7SEvalZero if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
1353*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1354*042d53a7SEvalZero bt_mesh_store_iv(true);
1355*042d53a7SEvalZero }
1356*042d53a7SEvalZero
1357*042d53a7SEvalZero k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
1358*042d53a7SEvalZero return;
1359*042d53a7SEvalZero }
1360*042d53a7SEvalZero
1361*042d53a7SEvalZero if (bt_mesh.iv_update) {
1362*042d53a7SEvalZero bt_mesh_beacon_ivu_initiator(true);
1363*042d53a7SEvalZero bt_mesh_net_iv_update(bt_mesh.iv_index, false);
1364*042d53a7SEvalZero } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1365*042d53a7SEvalZero bt_mesh_store_iv(true);
1366*042d53a7SEvalZero }
1367*042d53a7SEvalZero }
1368*042d53a7SEvalZero
bt_mesh_net_start(void)1369*042d53a7SEvalZero void bt_mesh_net_start(void)
1370*042d53a7SEvalZero {
1371*042d53a7SEvalZero if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
1372*042d53a7SEvalZero bt_mesh_beacon_enable();
1373*042d53a7SEvalZero } else {
1374*042d53a7SEvalZero bt_mesh_beacon_disable();
1375*042d53a7SEvalZero }
1376*042d53a7SEvalZero
1377*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
1378*042d53a7SEvalZero bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
1379*042d53a7SEvalZero bt_mesh_proxy_gatt_enable();
1380*042d53a7SEvalZero bt_mesh_adv_update();
1381*042d53a7SEvalZero }
1382*042d53a7SEvalZero
1383*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
1384*042d53a7SEvalZero bt_mesh_lpn_init();
1385*042d53a7SEvalZero } else {
1386*042d53a7SEvalZero bt_mesh_scan_enable();
1387*042d53a7SEvalZero }
1388*042d53a7SEvalZero
1389*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
1390*042d53a7SEvalZero bt_mesh_friend_init();
1391*042d53a7SEvalZero }
1392*042d53a7SEvalZero
1393*042d53a7SEvalZero if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
1394*042d53a7SEvalZero u16_t net_idx = bt_mesh.sub[0].net_idx;
1395*042d53a7SEvalZero u16_t addr = bt_mesh_primary_addr();
1396*042d53a7SEvalZero
1397*042d53a7SEvalZero bt_mesh_prov_complete(net_idx, addr);
1398*042d53a7SEvalZero }
1399*042d53a7SEvalZero }
1400*042d53a7SEvalZero
bt_mesh_net_init(void)1401*042d53a7SEvalZero void bt_mesh_net_init(void)
1402*042d53a7SEvalZero {
1403*042d53a7SEvalZero k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh);
1404*042d53a7SEvalZero
1405*042d53a7SEvalZero k_work_init(&bt_mesh.local_work, bt_mesh_net_local);
1406*042d53a7SEvalZero net_buf_slist_init(&bt_mesh.local_queue);
1407*042d53a7SEvalZero }
1408