1 /*
2 * Copyright (C) 2019 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "mesh_keys.c"
39
40 #include <string.h>
41 #include <stdio.h>
42
43 #include "mesh/mesh_keys.h"
44
45 #include "btstack_util.h"
46 #include "btstack_memory.h"
47 #include "btstack_config.h"
48
49 // network key list
50 static btstack_linked_list_t network_keys;
51 static uint8_t mesh_network_key_used[MAX_NR_MESH_NETWORK_KEYS];
52
mesh_network_key_init(void)53 void mesh_network_key_init(void){
54 network_keys = NULL;
55 }
56
mesh_network_key_get_free_index(void)57 uint16_t mesh_network_key_get_free_index(void){
58 uint16_t i;
59 for (i=0;i < MAX_NR_MESH_NETWORK_KEYS ; i++){
60 if (mesh_network_key_used[i] == 0){
61 return i;
62 }
63 }
64 return MESH_KEYS_INVALID_INDEX;
65 }
66
mesh_network_key_add(mesh_network_key_t * network_key)67 void mesh_network_key_add(mesh_network_key_t * network_key){
68 mesh_network_key_used[network_key->internal_index] = 1;
69 btstack_linked_list_add_tail(&network_keys, (btstack_linked_item_t *) network_key);
70 }
71
mesh_network_key_remove(mesh_network_key_t * network_key)72 bool mesh_network_key_remove(mesh_network_key_t * network_key){
73 mesh_network_key_used[network_key->internal_index] = 0;
74 return btstack_linked_list_remove(&network_keys, (btstack_linked_item_t *) network_key);
75 }
76
mesh_network_key_list_get(uint16_t netkey_index)77 mesh_network_key_t * mesh_network_key_list_get(uint16_t netkey_index){
78 btstack_linked_list_iterator_t it;
79 btstack_linked_list_iterator_init(&it, &network_keys);
80 while (btstack_linked_list_iterator_has_next(&it)){
81 mesh_network_key_t * item = (mesh_network_key_t *) btstack_linked_list_iterator_next(&it);
82 if (item->netkey_index == netkey_index) return item;
83 }
84 return NULL;
85 }
86
mesh_network_key_list_count(void)87 int mesh_network_key_list_count(void){
88 return btstack_linked_list_count(&network_keys);
89 }
90
91 // mesh network key iterator over all keys
mesh_network_key_iterator_init(mesh_network_key_iterator_t * it)92 void mesh_network_key_iterator_init(mesh_network_key_iterator_t *it){
93 btstack_linked_list_iterator_init(&it->it, &network_keys);
94 }
95
mesh_network_key_iterator_has_more(mesh_network_key_iterator_t * it)96 int mesh_network_key_iterator_has_more(mesh_network_key_iterator_t *it){
97 return btstack_linked_list_iterator_has_next(&it->it);
98 }
99
mesh_network_key_iterator_get_next(mesh_network_key_iterator_t * it)100 mesh_network_key_t * mesh_network_key_iterator_get_next(mesh_network_key_iterator_t *it){
101 return (mesh_network_key_t *) btstack_linked_list_iterator_next(&it->it);
102 }
103
104 // mesh network key iterator for a given nid
mesh_network_key_nid_iterator_init(mesh_network_key_iterator_t * it,uint8_t nid)105 void mesh_network_key_nid_iterator_init(mesh_network_key_iterator_t *it, uint8_t nid){
106 btstack_linked_list_iterator_init(&it->it, &network_keys);
107 it->key = NULL;
108 it->nid = nid;
109 }
110
mesh_network_key_nid_iterator_has_more(mesh_network_key_iterator_t * it)111 int mesh_network_key_nid_iterator_has_more(mesh_network_key_iterator_t *it){
112 // find next matching key
113 while (true){
114 if (it->key && it->key->nid == it->nid) return 1;
115 if (!btstack_linked_list_iterator_has_next(&it->it)) break;
116 it->key = (mesh_network_key_t *) btstack_linked_list_iterator_next(&it->it);
117 }
118 return 0;
119 }
120
mesh_network_key_nid_iterator_get_next(mesh_network_key_iterator_t * it)121 mesh_network_key_t * mesh_network_key_nid_iterator_get_next(mesh_network_key_iterator_t *it){
122 mesh_network_key_t * key = it->key;
123 it->key = NULL;
124 return key;
125 }
126
127
128 // application key list
129
130 // key management
131 static mesh_transport_key_t mesh_transport_device_key;
132 static btstack_linked_list_t application_keys;
133
134 static uint8_t mesh_transport_key_used[MAX_NR_MESH_TRANSPORT_KEYS];
135
mesh_transport_set_device_key(const uint8_t * device_key)136 void mesh_transport_set_device_key(const uint8_t * device_key){
137 mesh_transport_device_key.appkey_index = MESH_DEVICE_KEY_INDEX;
138 mesh_transport_device_key.aid = 0;
139 mesh_transport_device_key.akf = 0;
140 mesh_transport_device_key.netkey_index = 0; // unused
141 (void)memcpy(mesh_transport_device_key.key, device_key, 16);
142
143 // use internal slot #0
144 mesh_transport_device_key.internal_index = 0;
145 mesh_transport_key_used[0] = 1;
146 }
147
mesh_transport_key_get_free_index(void)148 uint16_t mesh_transport_key_get_free_index(void){
149 // find empty slot, skip slot #0 reserved for device key
150 uint16_t i;
151 for (i=1;i < MAX_NR_MESH_TRANSPORT_KEYS ; i++){
152 if (mesh_transport_key_used[i] == 0){
153 return i;
154 }
155 }
156 return 0;
157 }
158
mesh_transport_key_add(mesh_transport_key_t * transport_key)159 void mesh_transport_key_add(mesh_transport_key_t * transport_key){
160 mesh_transport_key_used[transport_key->internal_index] = 1;
161 btstack_linked_list_add_tail(&application_keys, (btstack_linked_item_t *) transport_key);
162 }
163
mesh_transport_key_remove(mesh_transport_key_t * transport_key)164 bool mesh_transport_key_remove(mesh_transport_key_t * transport_key){
165 mesh_transport_key_used[transport_key->internal_index] = 0;
166 return btstack_linked_list_remove(&application_keys, (btstack_linked_item_t *) transport_key);
167 }
168
mesh_transport_key_get(uint16_t appkey_index)169 mesh_transport_key_t * mesh_transport_key_get(uint16_t appkey_index){
170 if (appkey_index == MESH_DEVICE_KEY_INDEX){
171 return &mesh_transport_device_key;
172 }
173 btstack_linked_list_iterator_t it;
174 btstack_linked_list_iterator_init(&it, &application_keys);
175 while (btstack_linked_list_iterator_has_next(&it)){
176 mesh_transport_key_t * item = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it);
177 if (item->appkey_index == appkey_index) return item;
178 }
179 return NULL;
180 }
181
182 // key iterator
mesh_transport_key_iterator_init(mesh_transport_key_iterator_t * it,uint16_t netkey_index)183 void mesh_transport_key_iterator_init(mesh_transport_key_iterator_t *it, uint16_t netkey_index){
184 btstack_linked_list_iterator_init(&it->it, &application_keys);
185 it->netkey_index = netkey_index;
186 it->key = NULL;
187 }
188
mesh_transport_key_iterator_has_more(mesh_transport_key_iterator_t * it)189 int mesh_transport_key_iterator_has_more(mesh_transport_key_iterator_t *it){
190 // find next matching key
191 while (true){
192 if (it->key && it->key->netkey_index == it->netkey_index) return 1;
193 if (!btstack_linked_list_iterator_has_next(&it->it)) break;
194 it->key = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it->it);
195 }
196 return 0;
197 }
198
mesh_transport_key_iterator_get_next(mesh_transport_key_iterator_t * it)199 mesh_transport_key_t * mesh_transport_key_iterator_get_next(mesh_transport_key_iterator_t *it){
200 mesh_transport_key_t * key = it->key;
201 it->key = NULL;
202 return key;
203 }
204
205 void
mesh_transport_key_aid_iterator_init(mesh_transport_key_iterator_t * it,uint16_t netkey_index,uint8_t akf,uint8_t aid)206 mesh_transport_key_aid_iterator_init(mesh_transport_key_iterator_t *it, uint16_t netkey_index, uint8_t akf, uint8_t aid) {
207 btstack_linked_list_iterator_init(&it->it, &application_keys);
208 it->netkey_index = netkey_index;
209 it->aid = aid;
210 it->akf = akf;
211 if (it->akf){
212 it->key = NULL;
213 } else {
214 it->key = &mesh_transport_device_key;
215 }
216 }
217
mesh_transport_key_aid_iterator_has_more(mesh_transport_key_iterator_t * it)218 int mesh_transport_key_aid_iterator_has_more(mesh_transport_key_iterator_t *it){
219 if (it->akf == 0){
220 return it->key != NULL;
221 }
222 // find next matching key
223 while (true){
224 if (it->key && it->key->aid == it->aid && it->key->netkey_index == it->netkey_index) return 1;
225 if (!btstack_linked_list_iterator_has_next(&it->it)) break;
226 it->key = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it->it);
227 }
228 return 0;
229 }
230
mesh_transport_key_aid_iterator_get_next(mesh_transport_key_iterator_t * it)231 mesh_transport_key_t * mesh_transport_key_aid_iterator_get_next(mesh_transport_key_iterator_t *it){
232 mesh_transport_key_t * key = it->key;
233 it->key = NULL;
234 return key;
235 }
236