1 /*
2  * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <errno.h>
9 
10 #include "mesh.h"
11 #include "mesh_common.h"
12 #include "access.h"
13 #include "beacon.h"
14 #include "foundation.h"
15 #include "proxy_client.h"
16 #include "provisioner_prov.h"
17 #include "provisioner_main.h"
18 
19 #if CONFIG_BLE_MESH_FAST_PROV
20 
21 #define ACTION_ENTER    0x01
22 #define ACTION_SUSPEND  0x02
23 #define ACTION_EXIT     0x03
24 
bt_mesh_fast_prov_dev_key_get(uint16_t dst)25 const uint8_t *bt_mesh_fast_prov_dev_key_get(uint16_t dst)
26 {
27     if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
28         BT_ERR("Invalid unicast address 0x%04x", dst);
29         return NULL;
30     }
31 
32     if (dst == bt_mesh_primary_addr()) {
33         return bt_mesh.dev_key;
34     }
35 
36     return bt_mesh_provisioner_dev_key_get(dst);
37 }
38 
bt_mesh_fast_prov_subnet_get(uint16_t net_idx)39 struct bt_mesh_subnet *bt_mesh_fast_prov_subnet_get(uint16_t net_idx)
40 {
41     struct bt_mesh_subnet *sub = NULL;
42     int i;
43 
44     for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
45         sub = &bt_mesh.sub[i];
46         if (sub->net_idx == net_idx) {
47             return sub;
48         }
49     }
50 
51     for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
52         sub = bt_mesh.p_sub[i];
53         if (sub && sub->net_idx == net_idx) {
54             return sub;
55         }
56     }
57 
58     return NULL;
59 }
60 
bt_mesh_fast_prov_app_key_find(uint16_t app_idx)61 struct bt_mesh_app_key *bt_mesh_fast_prov_app_key_find(uint16_t app_idx)
62 {
63     struct bt_mesh_app_key *key = NULL;
64     int i;
65 
66     for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
67         key = &bt_mesh.app_keys[i];
68         if (key->net_idx != BLE_MESH_KEY_UNUSED &&
69             key->app_idx == app_idx) {
70             return key;
71         }
72     }
73 
74     for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) {
75         key = bt_mesh.p_app_keys[i];
76         if (key && key->net_idx != BLE_MESH_KEY_UNUSED &&
77             key->app_idx == app_idx) {
78             return key;
79         }
80     }
81 
82     return NULL;
83 }
84 
bt_mesh_set_fast_prov_net_idx(uint16_t net_idx)85 uint8_t bt_mesh_set_fast_prov_net_idx(uint16_t net_idx)
86 {
87     /* Set net_idx for fast provisioning */
88     bt_mesh_provisioner_set_fast_prov_net_idx(net_idx);
89 
90     if (bt_mesh_fast_prov_subnet_get(net_idx) == NULL) {
91         /* If NetKey is not found, wait for NetKey to be added. */
92         BT_WARN("Wait for NetKey for fast provisioning");
93         return 0x01; /*status: Wait for NetKey */
94     }
95 
96     return 0x0; /* status: Succeed */
97 }
98 
bt_mesh_fast_prov_net_key_add(const uint8_t net_key[16])99 uint8_t bt_mesh_fast_prov_net_key_add(const uint8_t net_key[16])
100 {
101     uint16_t net_idx = 0U;
102     int err = 0;
103 
104     net_idx = bt_mesh_provisioner_get_fast_prov_net_idx();
105     bt_mesh.p_net_idx_next = net_idx;
106 
107     err = bt_mesh_provisioner_local_net_key_add(net_key, &net_idx);
108     if (err) {
109         BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
110         return 0x01; /* status: Add NetKey failed */
111     };
112 
113     bt_mesh_provisioner_set_fast_prov_net_idx(net_idx);
114     return 0x0; /* status: Succeed */
115 }
116 
bt_mesh_fast_prov_net_key_get(uint16_t net_idx)117 const uint8_t *bt_mesh_fast_prov_net_key_get(uint16_t net_idx)
118 {
119     struct bt_mesh_subnet *sub = NULL;
120 
121     sub = bt_mesh_fast_prov_subnet_get(net_idx);
122     if (!sub) {
123         BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
124         return NULL;
125     }
126 
127     return (sub->kr_flag ? sub->keys[1].net : sub->keys[0].net);
128 }
129 
bt_mesh_get_fast_prov_app_key(uint16_t net_idx,uint16_t app_idx)130 const uint8_t *bt_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx)
131 {
132     struct bt_mesh_app_key *key = NULL;
133 
134     key = bt_mesh_fast_prov_app_key_find(app_idx);
135     if (!key) {
136         BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx);
137         return NULL;
138     }
139 
140     return (key->updated ? key->keys[1].val : key->keys[0].val);
141 }
142 
bt_mesh_set_fast_prov_action(uint8_t action)143 uint8_t bt_mesh_set_fast_prov_action(uint8_t action)
144 {
145     if (!action || action > ACTION_EXIT) {
146         return 0x01;
147     }
148 
149     if ((!bt_mesh_is_provisioner_en() && (action == ACTION_SUSPEND || action == ACTION_EXIT)) ||
150         (bt_mesh_is_provisioner_en() && (action == ACTION_ENTER))) {
151         BT_WARN("%s, Already", __func__);
152         return 0x0;
153     }
154 
155     if (action == ACTION_ENTER) {
156         if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
157             bt_mesh_beacon_disable();
158         }
159         if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
160             bt_mesh_proxy_client_prov_enable();
161         }
162         bt_mesh_provisioner_set_primary_elem_addr(bt_mesh_primary_addr());
163         bt_mesh_provisioner_set_prov_bearer(BLE_MESH_PROV_ADV, false);
164         bt_mesh_provisioner_fast_prov_enable(true);
165         bt_mesh_atomic_or(bt_mesh.flags, BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV));
166     } else {
167         if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) {
168             bt_mesh_proxy_client_prov_disable();
169         }
170         if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
171             bt_mesh_beacon_enable();
172         }
173         bt_mesh_atomic_and(bt_mesh.flags, ~(BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV)));
174         bt_mesh_provisioner_fast_prov_enable(false);
175         if (action == ACTION_EXIT) {
176             bt_mesh_provisioner_remove_node(NULL);
177         }
178     }
179 
180     return 0x0;
181 }
182 #endif /* CONFIG_BLE_MESH_FAST_PROV */
183