xref: /btstack/src/mesh/mesh_keys.c (revision a5a7b6da93a734de273f68a4770fffd1d7ae3888)
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 MATTHIAS
24  * RINGWALD 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 
53 void mesh_network_key_init(void){
54     network_keys = NULL;
55 }
56 
57 uint16_t mesh_network_key_get_free_index(void){
58     // find empty slot, skip slot #0 reserved for primary network key
59     uint16_t i;
60     for (i=1;i < MAX_NR_MESH_NETWORK_KEYS ; i++){
61         if (mesh_network_key_used[i] == 0){
62             return i;
63         }
64     }
65     return 0;
66 }
67 
68 void mesh_network_key_add(mesh_network_key_t * network_key){
69     mesh_network_key_used[network_key->internal_index] = 1;
70     btstack_linked_list_add_tail(&network_keys, (btstack_linked_item_t *) network_key);
71 }
72 
73 int mesh_network_key_remove(mesh_network_key_t * network_key){
74     mesh_network_key_used[network_key->internal_index] = 1;
75     return btstack_linked_list_remove(&network_keys, (btstack_linked_item_t *) network_key);
76 }
77 
78 mesh_network_key_t * mesh_network_key_list_get(uint16_t netkey_index){
79     btstack_linked_list_iterator_t it;
80     btstack_linked_list_iterator_init(&it, &network_keys);
81     while (btstack_linked_list_iterator_has_next(&it)){
82         mesh_network_key_t * item = (mesh_network_key_t *) btstack_linked_list_iterator_next(&it);
83         if (item->netkey_index == netkey_index) return item;
84     }
85     return NULL;
86 }
87 
88 int mesh_network_key_list_count(void){
89     return btstack_linked_list_count(&network_keys);
90 }
91 
92 // mesh network key iterator over all keys
93 void mesh_network_key_iterator_init(mesh_network_key_iterator_t *it){
94     btstack_linked_list_iterator_init(&it->it, &network_keys);
95 }
96 
97 int mesh_network_key_iterator_has_more(mesh_network_key_iterator_t *it){
98     return btstack_linked_list_iterator_has_next(&it->it);
99 }
100 
101 mesh_network_key_t * mesh_network_key_iterator_get_next(mesh_network_key_iterator_t *it){
102     return (mesh_network_key_t *) btstack_linked_list_iterator_next(&it->it);
103 }
104 
105 // mesh network key iterator for a given nid
106 void mesh_network_key_nid_iterator_init(mesh_network_key_iterator_t *it, uint8_t nid){
107     btstack_linked_list_iterator_init(&it->it, &network_keys);
108     it->key = NULL;
109     it->nid = nid;
110 }
111 
112 int mesh_network_key_nid_iterator_has_more(mesh_network_key_iterator_t *it){
113     // find next matching key
114     while (1){
115         if (it->key && it->key->nid == it->nid) return 1;
116         if (!btstack_linked_list_iterator_has_next(&it->it)) break;
117         it->key = (mesh_network_key_t *) btstack_linked_list_iterator_next(&it->it);
118     }
119     return 0;
120 }
121 
122 mesh_network_key_t * mesh_network_key_nid_iterator_get_next(mesh_network_key_iterator_t *it){
123     mesh_network_key_t * key = it->key;
124     it->key = NULL;
125     return key;
126 }
127 
128 
129 // application key list
130 
131 // key management
132 static mesh_transport_key_t   mesh_transport_device_key;
133 static btstack_linked_list_t  application_keys;
134 
135 static uint8_t mesh_transport_key_used[MAX_NR_MESH_TRANSPORT_KEYS];
136 
137 void mesh_transport_set_device_key(const uint8_t * device_key){
138     mesh_transport_device_key.appkey_index = MESH_DEVICE_KEY_INDEX;
139     mesh_transport_device_key.aid   = 0;
140     mesh_transport_device_key.akf   = 0;
141     mesh_transport_device_key.netkey_index = 0; // unused
142     memcpy(mesh_transport_device_key.key, device_key, 16);
143 
144     // use internal slot #0
145     mesh_transport_device_key.internal_index = 0;
146     mesh_transport_key_used[0] = 1;
147 }
148 
149 uint16_t mesh_transport_key_get_free_index(void){
150     // find empty slot, skip slot #0 reserved for device key
151     uint16_t i;
152     for (i=1;i < MAX_NR_MESH_TRANSPORT_KEYS ; i++){
153         if (mesh_transport_key_used[i] == 0){
154             return i;
155         }
156     }
157     return 0;
158 }
159 
160 void mesh_transport_key_add(mesh_transport_key_t * transport_key){
161     mesh_transport_key_used[transport_key->internal_index] = 1;
162     btstack_linked_list_add_tail(&application_keys, (btstack_linked_item_t *) transport_key);
163 }
164 
165 int mesh_transport_key_remove(mesh_transport_key_t * transport_key){
166     mesh_transport_key_used[transport_key->internal_index] = 0;
167     return btstack_linked_list_remove(&application_keys, (btstack_linked_item_t *) transport_key);
168 }
169 
170 mesh_transport_key_t * mesh_transport_key_get(uint16_t appkey_index){
171     if (appkey_index == MESH_DEVICE_KEY_INDEX){
172         return &mesh_transport_device_key;
173     }
174     btstack_linked_list_iterator_t it;
175     btstack_linked_list_iterator_init(&it, &application_keys);
176     while (btstack_linked_list_iterator_has_next(&it)){
177         mesh_transport_key_t * item = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it);
178         if (item->appkey_index == appkey_index) return item;
179     }
180     return NULL;
181 }
182 
183 // key iterator
184 void mesh_transport_key_iterator_init(mesh_transport_key_iterator_t *it, uint16_t netkey_index){
185     btstack_linked_list_iterator_init(&it->it, &application_keys);
186     it->netkey_index = netkey_index;
187     it->key = NULL;
188 }
189 
190 int mesh_transport_key_iterator_has_more(mesh_transport_key_iterator_t *it){
191     // find next matching key
192     while (1){
193         if (it->key && it->key->netkey_index == it->netkey_index) return 1;
194         if (!btstack_linked_list_iterator_has_next(&it->it)) break;
195         it->key = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it->it);
196     }
197     return 0;
198 }
199 
200 mesh_transport_key_t * mesh_transport_key_iterator_get_next(mesh_transport_key_iterator_t *it){
201     mesh_transport_key_t * key = it->key;
202     it->key = NULL;
203     return key;
204 }
205 
206 void
207 mesh_transport_key_aid_iterator_init(mesh_transport_key_iterator_t *it, uint16_t netkey_index, uint8_t akf, uint8_t aid) {
208     btstack_linked_list_iterator_init(&it->it, &application_keys);
209     it->netkey_index = netkey_index;
210     it->aid      = aid;
211     it->akf      = akf;
212     if (it->akf){
213         it->key = NULL;
214     } else {
215         it->key = &mesh_transport_device_key;
216     }
217 }
218 
219 int mesh_transport_key_aid_iterator_has_more(mesh_transport_key_iterator_t *it){
220     if (it->akf == 0){
221         return it->key != NULL;
222     }
223     // find next matching key
224     while (1){
225         if (it->key && it->key->aid == it->aid && it->key->netkey_index == it->netkey_index) return 1;
226         if (!btstack_linked_list_iterator_has_next(&it->it)) break;
227         it->key = (mesh_transport_key_t *) btstack_linked_list_iterator_next(&it->it);
228     }
229     return 0;
230 }
231 
232 mesh_transport_key_t * mesh_transport_key_aid_iterator_get_next(mesh_transport_key_iterator_t *it){
233     mesh_transport_key_t * key = it->key;
234     it->key = NULL;
235     return key;
236 }
237