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