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