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