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 53 void mesh_network_key_init(void){ 54 network_keys = NULL; 55 } 56 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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