xref: /btstack/src/mesh/mesh_keys.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
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