cvb

Fork of nrf51-sdk by Lancaster University

Committer:
tb942
Date:
Tue Aug 14 18:27:20 2018 +0000
Revision:
9:d3dd910b0f4b
Parent:
0:bc2961fa1ef0

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 0:bc2961fa1ef0 1 /*
Jonathan Austin 0:bc2961fa1ef0 2 * Copyright (c) Nordic Semiconductor ASA
Jonathan Austin 0:bc2961fa1ef0 3 * All rights reserved.
Jonathan Austin 0:bc2961fa1ef0 4 *
Jonathan Austin 0:bc2961fa1ef0 5 * Redistribution and use in source and binary forms, with or without modification,
Jonathan Austin 0:bc2961fa1ef0 6 * are permitted provided that the following conditions are met:
Jonathan Austin 0:bc2961fa1ef0 7 *
Jonathan Austin 0:bc2961fa1ef0 8 * 1. Redistributions of source code must retain the above copyright notice, this
Jonathan Austin 0:bc2961fa1ef0 9 * list of conditions and the following disclaimer.
Jonathan Austin 0:bc2961fa1ef0 10 *
Jonathan Austin 0:bc2961fa1ef0 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
Jonathan Austin 0:bc2961fa1ef0 12 * list of conditions and the following disclaimer in the documentation and/or
Jonathan Austin 0:bc2961fa1ef0 13 * other materials provided with the distribution.
Jonathan Austin 0:bc2961fa1ef0 14 *
Jonathan Austin 0:bc2961fa1ef0 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
Jonathan Austin 0:bc2961fa1ef0 16 * contributors to this software may be used to endorse or promote products
Jonathan Austin 0:bc2961fa1ef0 17 * derived from this software without specific prior written permission.
Jonathan Austin 0:bc2961fa1ef0 18 *
Jonathan Austin 0:bc2961fa1ef0 19 *
Jonathan Austin 0:bc2961fa1ef0 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Jonathan Austin 0:bc2961fa1ef0 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Jonathan Austin 0:bc2961fa1ef0 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Jonathan Austin 0:bc2961fa1ef0 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
Jonathan Austin 0:bc2961fa1ef0 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Jonathan Austin 0:bc2961fa1ef0 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Jonathan Austin 0:bc2961fa1ef0 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
Jonathan Austin 0:bc2961fa1ef0 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Jonathan Austin 0:bc2961fa1ef0 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Jonathan Austin 0:bc2961fa1ef0 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Jonathan Austin 0:bc2961fa1ef0 30 *
Jonathan Austin 0:bc2961fa1ef0 31 */
Jonathan Austin 0:bc2961fa1ef0 32
Jonathan Austin 0:bc2961fa1ef0 33 #include "id_manager.h"
Jonathan Austin 0:bc2961fa1ef0 34
Jonathan Austin 0:bc2961fa1ef0 35 #include <string.h>
Jonathan Austin 0:bc2961fa1ef0 36 #include "nrf_soc.h"
Jonathan Austin 0:bc2961fa1ef0 37 #include "ble_gap.h"
Jonathan Austin 0:bc2961fa1ef0 38 #include "ble_conn_state.h"
Jonathan Austin 0:bc2961fa1ef0 39 #include "peer_manager_types.h"
Jonathan Austin 0:bc2961fa1ef0 40 #include "peer_database.h"
Jonathan Austin 0:bc2961fa1ef0 41 #include "nordic_common.h"
Jonathan Austin 0:bc2961fa1ef0 42
Jonathan Austin 0:bc2961fa1ef0 43 #define IM_MAX_CONN_HANDLES 8
Jonathan Austin 0:bc2961fa1ef0 44 #define IM_NO_INVALID_CONN_HANDLES 0xFF
Jonathan Austin 0:bc2961fa1ef0 45 #define MAX_REGISTRANTS 3
Jonathan Austin 0:bc2961fa1ef0 46 #define WHITELIST_MAX_COUNT MAX(BLE_GAP_WHITELIST_ADDR_MAX_COUNT, \
Jonathan Austin 0:bc2961fa1ef0 47 BLE_GAP_WHITELIST_IRK_MAX_COUNT)
Jonathan Austin 0:bc2961fa1ef0 48 #define IM_ADDR_CLEARTEXT_LENGTH 3
Jonathan Austin 0:bc2961fa1ef0 49 #define IM_ADDR_CIPHERTEXT_LENGTH 3
Jonathan Austin 0:bc2961fa1ef0 50
Jonathan Austin 0:bc2961fa1ef0 51 #define MODULE_INITIALIZED (m_im.n_registrants > 0)
Jonathan Austin 0:bc2961fa1ef0 52
Jonathan Austin 0:bc2961fa1ef0 53 #define VERIFY_MODULE_INITIALIZED() \
Jonathan Austin 0:bc2961fa1ef0 54 do \
Jonathan Austin 0:bc2961fa1ef0 55 { \
Jonathan Austin 0:bc2961fa1ef0 56 if (!MODULE_INITIALIZED) \
Jonathan Austin 0:bc2961fa1ef0 57 { \
Jonathan Austin 0:bc2961fa1ef0 58 return NRF_ERROR_INVALID_STATE; \
Jonathan Austin 0:bc2961fa1ef0 59 } \
Jonathan Austin 0:bc2961fa1ef0 60 } while(0)
Jonathan Austin 0:bc2961fa1ef0 61
Jonathan Austin 0:bc2961fa1ef0 62 #define VERIFY_PARAM_NOT_NULL(param) \
Jonathan Austin 0:bc2961fa1ef0 63 do \
Jonathan Austin 0:bc2961fa1ef0 64 { \
Jonathan Austin 0:bc2961fa1ef0 65 if (param == NULL) \
Jonathan Austin 0:bc2961fa1ef0 66 { \
Jonathan Austin 0:bc2961fa1ef0 67 return NRF_ERROR_NULL; \
Jonathan Austin 0:bc2961fa1ef0 68 } \
Jonathan Austin 0:bc2961fa1ef0 69 } while(0)
Jonathan Austin 0:bc2961fa1ef0 70
Jonathan Austin 0:bc2961fa1ef0 71
Jonathan Austin 0:bc2961fa1ef0 72 typedef struct
Jonathan Austin 0:bc2961fa1ef0 73 {
Jonathan Austin 0:bc2961fa1ef0 74 pm_peer_id_t peer_id;
Jonathan Austin 0:bc2961fa1ef0 75 uint16_t conn_handle;
Jonathan Austin 0:bc2961fa1ef0 76 ble_gap_addr_t peer_address;
Jonathan Austin 0:bc2961fa1ef0 77 } im_connection_t;
Jonathan Austin 0:bc2961fa1ef0 78
Jonathan Austin 0:bc2961fa1ef0 79 typedef struct
Jonathan Austin 0:bc2961fa1ef0 80 {
Jonathan Austin 0:bc2961fa1ef0 81 im_evt_handler_t evt_handlers[MAX_REGISTRANTS];
Jonathan Austin 0:bc2961fa1ef0 82 uint8_t n_registrants;
Jonathan Austin 0:bc2961fa1ef0 83 im_connection_t connections[8];
Jonathan Austin 0:bc2961fa1ef0 84 pm_peer_id_t whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
Jonathan Austin 0:bc2961fa1ef0 85 ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
Jonathan Austin 0:bc2961fa1ef0 86 ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
Jonathan Austin 0:bc2961fa1ef0 87 uint8_t n_whitelist_peer_ids;
Jonathan Austin 0:bc2961fa1ef0 88 ble_conn_state_user_flag_id_t conn_state_user_flag_id;
Jonathan Austin 0:bc2961fa1ef0 89 } im_t;
Jonathan Austin 0:bc2961fa1ef0 90
Jonathan Austin 0:bc2961fa1ef0 91 static im_t m_im = {.n_registrants = 0};
Jonathan Austin 0:bc2961fa1ef0 92
Jonathan Austin 0:bc2961fa1ef0 93 static void internal_state_reset()
Jonathan Austin 0:bc2961fa1ef0 94 {
Jonathan Austin 0:bc2961fa1ef0 95 memset(&m_im, 0, sizeof(im_t));
Jonathan Austin 0:bc2961fa1ef0 96 m_im.n_registrants = 0;
Jonathan Austin 0:bc2961fa1ef0 97 m_im.n_whitelist_peer_ids = 0;
Jonathan Austin 0:bc2961fa1ef0 98 m_im.conn_state_user_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID;
Jonathan Austin 0:bc2961fa1ef0 99 for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
Jonathan Austin 0:bc2961fa1ef0 100 {
Jonathan Austin 0:bc2961fa1ef0 101 m_im.connections[i].conn_handle = BLE_CONN_HANDLE_INVALID;
Jonathan Austin 0:bc2961fa1ef0 102 }
Jonathan Austin 0:bc2961fa1ef0 103 }
Jonathan Austin 0:bc2961fa1ef0 104
Jonathan Austin 0:bc2961fa1ef0 105
Jonathan Austin 0:bc2961fa1ef0 106 /**@brief Function for sending an event to all registered event handlers.
Jonathan Austin 0:bc2961fa1ef0 107 *
Jonathan Austin 0:bc2961fa1ef0 108 * @param[in] p_event The event to distribute.
Jonathan Austin 0:bc2961fa1ef0 109 */
Jonathan Austin 0:bc2961fa1ef0 110 static void evt_send(im_evt_t * p_event)
Jonathan Austin 0:bc2961fa1ef0 111 {
Jonathan Austin 0:bc2961fa1ef0 112 for (uint32_t i = 0; i < m_im.n_registrants; i++)
Jonathan Austin 0:bc2961fa1ef0 113 {
Jonathan Austin 0:bc2961fa1ef0 114 m_im.evt_handlers[i](p_event);
Jonathan Austin 0:bc2961fa1ef0 115 }
Jonathan Austin 0:bc2961fa1ef0 116 }
Jonathan Austin 0:bc2961fa1ef0 117
Jonathan Austin 0:bc2961fa1ef0 118 /**@brief Function finding a free position in m_im.connections.
Jonathan Austin 0:bc2961fa1ef0 119 *
Jonathan Austin 0:bc2961fa1ef0 120 * @detail All connection handles in the m_im.connections array are checked against the connection
Jonathan Austin 0:bc2961fa1ef0 121 * state module. The index of the first one that is not a connection handle for a current
Jonathan Austin 0:bc2961fa1ef0 122 * connection is returned. This position in the array can safely be used for a new connection.
Jonathan Austin 0:bc2961fa1ef0 123 *
Jonathan Austin 0:bc2961fa1ef0 124 * @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free
Jonathan Austin 0:bc2961fa1ef0 125 position exists.
Jonathan Austin 0:bc2961fa1ef0 126 */
Jonathan Austin 0:bc2961fa1ef0 127 uint8_t get_free_connection()
Jonathan Austin 0:bc2961fa1ef0 128 {
Jonathan Austin 0:bc2961fa1ef0 129 for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
Jonathan Austin 0:bc2961fa1ef0 130 {
Jonathan Austin 0:bc2961fa1ef0 131 // Query the connection state module to check if the connection handle does not belong to a
Jonathan Austin 0:bc2961fa1ef0 132 // valid connection.
Jonathan Austin 0:bc2961fa1ef0 133 if (!ble_conn_state_user_flag_get(m_im.connections[i].conn_handle, m_im.conn_state_user_flag_id))
Jonathan Austin 0:bc2961fa1ef0 134 {
Jonathan Austin 0:bc2961fa1ef0 135 return i;
Jonathan Austin 0:bc2961fa1ef0 136 }
Jonathan Austin 0:bc2961fa1ef0 137 }
Jonathan Austin 0:bc2961fa1ef0 138 // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
Jonathan Austin 0:bc2961fa1ef0 139 return IM_NO_INVALID_CONN_HANDLES;
Jonathan Austin 0:bc2961fa1ef0 140 }
Jonathan Austin 0:bc2961fa1ef0 141
Jonathan Austin 0:bc2961fa1ef0 142
Jonathan Austin 0:bc2961fa1ef0 143 /**@brief Function finding a particular connection handle m_im.connections.
Jonathan Austin 0:bc2961fa1ef0 144 *
Jonathan Austin 0:bc2961fa1ef0 145 * @param[in] conn_handle The handle to find.
Jonathan Austin 0:bc2961fa1ef0 146 *
Jonathan Austin 0:bc2961fa1ef0 147 * @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the
Jonathan Austin 0:bc2961fa1ef0 148 * handle was not found.
Jonathan Austin 0:bc2961fa1ef0 149 */
Jonathan Austin 0:bc2961fa1ef0 150 uint8_t get_connection_by_conn_handle(uint16_t conn_handle)
Jonathan Austin 0:bc2961fa1ef0 151 {
Jonathan Austin 0:bc2961fa1ef0 152 if (ble_conn_state_user_flag_get(conn_handle, m_im.conn_state_user_flag_id))
Jonathan Austin 0:bc2961fa1ef0 153 {
Jonathan Austin 0:bc2961fa1ef0 154 for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
Jonathan Austin 0:bc2961fa1ef0 155 {
Jonathan Austin 0:bc2961fa1ef0 156 if (m_im.connections[i].conn_handle == conn_handle)
Jonathan Austin 0:bc2961fa1ef0 157 {
Jonathan Austin 0:bc2961fa1ef0 158 return i;
Jonathan Austin 0:bc2961fa1ef0 159 }
Jonathan Austin 0:bc2961fa1ef0 160 }
Jonathan Austin 0:bc2961fa1ef0 161 }
Jonathan Austin 0:bc2961fa1ef0 162 // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
Jonathan Austin 0:bc2961fa1ef0 163 return IM_NO_INVALID_CONN_HANDLES;
Jonathan Austin 0:bc2961fa1ef0 164 }
Jonathan Austin 0:bc2961fa1ef0 165
Jonathan Austin 0:bc2961fa1ef0 166
Jonathan Austin 0:bc2961fa1ef0 167 /**@brief Function for registering a new connection instance.
Jonathan Austin 0:bc2961fa1ef0 168 *
Jonathan Austin 0:bc2961fa1ef0 169 * @param[in] conn_handle The handle of the new connection.
Jonathan Austin 0:bc2961fa1ef0 170 * @param[in] p_ble_addr The address used to connect.
Jonathan Austin 0:bc2961fa1ef0 171 *
Jonathan Austin 0:bc2961fa1ef0 172 * @return Either the index of the new connection in the array or IM_NO_INVALID_CONN_HANDLES if no
Jonathan Austin 0:bc2961fa1ef0 173 * free position exists.
Jonathan Austin 0:bc2961fa1ef0 174 */
Jonathan Austin 0:bc2961fa1ef0 175 uint8_t new_connection(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr)
Jonathan Austin 0:bc2961fa1ef0 176 {
Jonathan Austin 0:bc2961fa1ef0 177 uint8_t conn_index = IM_NO_INVALID_CONN_HANDLES;
Jonathan Austin 0:bc2961fa1ef0 178
Jonathan Austin 0:bc2961fa1ef0 179 if ((p_ble_addr != NULL) && (conn_handle != BLE_CONN_HANDLE_INVALID))
Jonathan Austin 0:bc2961fa1ef0 180 {
Jonathan Austin 0:bc2961fa1ef0 181 ble_conn_state_user_flag_set(conn_handle, m_im.conn_state_user_flag_id, true);
Jonathan Austin 0:bc2961fa1ef0 182
Jonathan Austin 0:bc2961fa1ef0 183 conn_index = get_connection_by_conn_handle(conn_handle);
Jonathan Austin 0:bc2961fa1ef0 184 if (conn_index == IM_NO_INVALID_CONN_HANDLES)
Jonathan Austin 0:bc2961fa1ef0 185 {
Jonathan Austin 0:bc2961fa1ef0 186 conn_index = get_free_connection();
Jonathan Austin 0:bc2961fa1ef0 187 }
Jonathan Austin 0:bc2961fa1ef0 188
Jonathan Austin 0:bc2961fa1ef0 189 if (conn_index != IM_NO_INVALID_CONN_HANDLES)
Jonathan Austin 0:bc2961fa1ef0 190 {
Jonathan Austin 0:bc2961fa1ef0 191 m_im.connections[conn_index].conn_handle = conn_handle;
Jonathan Austin 0:bc2961fa1ef0 192 m_im.connections[conn_index].peer_id = PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 193 m_im.connections[conn_index].peer_address = *p_ble_addr;
Jonathan Austin 0:bc2961fa1ef0 194 }
Jonathan Austin 0:bc2961fa1ef0 195 }
Jonathan Austin 0:bc2961fa1ef0 196 return conn_index;
Jonathan Austin 0:bc2961fa1ef0 197 }
Jonathan Austin 0:bc2961fa1ef0 198
Jonathan Austin 0:bc2961fa1ef0 199
Jonathan Austin 0:bc2961fa1ef0 200 /**@brief Function checking the validity of an IRK
Jonathan Austin 0:bc2961fa1ef0 201 *
Jonathan Austin 0:bc2961fa1ef0 202 * @detail An all-zero IRK is not valid. This function will check if a given IRK is valid.
Jonathan Austin 0:bc2961fa1ef0 203 *
Jonathan Austin 0:bc2961fa1ef0 204 * @param[in] irk The IRK for which the validity is going to be checked.
Jonathan Austin 0:bc2961fa1ef0 205 *
Jonathan Austin 0:bc2961fa1ef0 206 * @retval true The IRK is valid.
Jonathan Austin 0:bc2961fa1ef0 207 * @retval false The IRK is invalid.
Jonathan Austin 0:bc2961fa1ef0 208 */
Jonathan Austin 0:bc2961fa1ef0 209 bool is_valid_irk(ble_gap_irk_t const * irk)
Jonathan Austin 0:bc2961fa1ef0 210 {
Jonathan Austin 0:bc2961fa1ef0 211 for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++)
Jonathan Austin 0:bc2961fa1ef0 212 {
Jonathan Austin 0:bc2961fa1ef0 213 if (irk->irk[i] != 0)
Jonathan Austin 0:bc2961fa1ef0 214 {
Jonathan Austin 0:bc2961fa1ef0 215 return true;
Jonathan Austin 0:bc2961fa1ef0 216 }
Jonathan Austin 0:bc2961fa1ef0 217 }
Jonathan Austin 0:bc2961fa1ef0 218 return false;
Jonathan Austin 0:bc2961fa1ef0 219 }
Jonathan Austin 0:bc2961fa1ef0 220
Jonathan Austin 0:bc2961fa1ef0 221
Jonathan Austin 0:bc2961fa1ef0 222 /**@brief Function for comparing two addresses to determine if they are identical
Jonathan Austin 0:bc2961fa1ef0 223 *
Jonathan Austin 0:bc2961fa1ef0 224 * @note The address type need to be identical, as well as every bit in the address itself.
Jonathan Austin 0:bc2961fa1ef0 225 *
Jonathan Austin 0:bc2961fa1ef0 226 * @param[in] p_addr1 The first address to be compared.
Jonathan Austin 0:bc2961fa1ef0 227 * @param[in] p_addr2 The second address to be compared.
Jonathan Austin 0:bc2961fa1ef0 228 *
Jonathan Austin 0:bc2961fa1ef0 229 * @retval true The addresses are identical.
Jonathan Austin 0:bc2961fa1ef0 230 * @retval false The addresses are not identical.
Jonathan Austin 0:bc2961fa1ef0 231 */
Jonathan Austin 0:bc2961fa1ef0 232 bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2)
Jonathan Austin 0:bc2961fa1ef0 233 {
Jonathan Austin 0:bc2961fa1ef0 234 if ((p_addr1 == NULL) || (p_addr2 == NULL))
Jonathan Austin 0:bc2961fa1ef0 235 {
Jonathan Austin 0:bc2961fa1ef0 236 return false;
Jonathan Austin 0:bc2961fa1ef0 237 }
Jonathan Austin 0:bc2961fa1ef0 238
Jonathan Austin 0:bc2961fa1ef0 239 // Check that the addr type is identical, return false if it is not
Jonathan Austin 0:bc2961fa1ef0 240 if (p_addr1->addr_type != p_addr2->addr_type)
Jonathan Austin 0:bc2961fa1ef0 241 {
Jonathan Austin 0:bc2961fa1ef0 242 return false;
Jonathan Austin 0:bc2961fa1ef0 243 }
Jonathan Austin 0:bc2961fa1ef0 244 // Check if the addr bytes are is identical
Jonathan Austin 0:bc2961fa1ef0 245 return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0);
Jonathan Austin 0:bc2961fa1ef0 246 }
Jonathan Austin 0:bc2961fa1ef0 247
Jonathan Austin 0:bc2961fa1ef0 248
Jonathan Austin 0:bc2961fa1ef0 249 void im_ble_evt_handler(ble_evt_t * ble_evt)
Jonathan Austin 0:bc2961fa1ef0 250 {
Jonathan Austin 0:bc2961fa1ef0 251 ret_code_t err_code;
Jonathan Austin 0:bc2961fa1ef0 252 switch (ble_evt->header.evt_id)
Jonathan Austin 0:bc2961fa1ef0 253 {
Jonathan Austin 0:bc2961fa1ef0 254 case BLE_GAP_EVT_CONNECTED:
Jonathan Austin 0:bc2961fa1ef0 255 {
Jonathan Austin 0:bc2961fa1ef0 256 pm_peer_id_t bonded_matching_peer_id = PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 257
Jonathan Austin 0:bc2961fa1ef0 258 if (ble_evt->evt.gap_evt.params.connected.irk_match == 1)
Jonathan Austin 0:bc2961fa1ef0 259 {
Jonathan Austin 0:bc2961fa1ef0 260 // The peer was matched using a whitelist.
Jonathan Austin 0:bc2961fa1ef0 261 bonded_matching_peer_id
Jonathan Austin 0:bc2961fa1ef0 262 = m_im.whitelist_peer_ids[ble_evt->evt.gap_evt.params.connected.irk_match_idx];
Jonathan Austin 0:bc2961fa1ef0 263 }
Jonathan Austin 0:bc2961fa1ef0 264 else if ( ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type
Jonathan Austin 0:bc2961fa1ef0 265 != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)
Jonathan Austin 0:bc2961fa1ef0 266 {
Jonathan Austin 0:bc2961fa1ef0 267 /* Search the database for bonding data matching the one that triggered the event.
Jonathan Austin 0:bc2961fa1ef0 268 * Public and static addresses can be matched on address alone, while resolvable
Jonathan Austin 0:bc2961fa1ef0 269 * random addresses can be resolved agains known IRKs. Non-resolvable random addresses
Jonathan Austin 0:bc2961fa1ef0 270 * are never matching because they are not longterm form of identification.
Jonathan Austin 0:bc2961fa1ef0 271 */
Jonathan Austin 0:bc2961fa1ef0 272 pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
Jonathan Austin 0:bc2961fa1ef0 273 while ( (compared_peer_id != PM_PEER_ID_INVALID)
Jonathan Austin 0:bc2961fa1ef0 274 && (bonded_matching_peer_id == PM_PEER_ID_INVALID))
Jonathan Austin 0:bc2961fa1ef0 275 {
Jonathan Austin 0:bc2961fa1ef0 276 pm_peer_data_flash_t compared_data;
Jonathan Austin 0:bc2961fa1ef0 277 switch (ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type)
Jonathan Austin 0:bc2961fa1ef0 278 {
Jonathan Austin 0:bc2961fa1ef0 279 case BLE_GAP_ADDR_TYPE_PUBLIC:
Jonathan Austin 0:bc2961fa1ef0 280 /* fall-through */
Jonathan Austin 0:bc2961fa1ef0 281 case BLE_GAP_ADDR_TYPE_RANDOM_STATIC:
Jonathan Austin 0:bc2961fa1ef0 282 err_code = pdb_read_buf_get(compared_peer_id,
Jonathan Austin 0:bc2961fa1ef0 283 PM_PEER_DATA_ID_BONDING,
Jonathan Austin 0:bc2961fa1ef0 284 &compared_data,
Jonathan Austin 0:bc2961fa1ef0 285 NULL);
Jonathan Austin 0:bc2961fa1ef0 286 if ((err_code == NRF_SUCCESS) &&
Jonathan Austin 0:bc2961fa1ef0 287 addr_compare(&ble_evt->evt.gap_evt.params.connected.peer_addr,
Jonathan Austin 0:bc2961fa1ef0 288 &compared_data.data.p_bonding_data->peer_id.id_addr_info)
Jonathan Austin 0:bc2961fa1ef0 289 )
Jonathan Austin 0:bc2961fa1ef0 290 {
Jonathan Austin 0:bc2961fa1ef0 291 bonded_matching_peer_id = compared_peer_id;
Jonathan Austin 0:bc2961fa1ef0 292 }
Jonathan Austin 0:bc2961fa1ef0 293 break;
Jonathan Austin 0:bc2961fa1ef0 294
Jonathan Austin 0:bc2961fa1ef0 295 case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE:
Jonathan Austin 0:bc2961fa1ef0 296 err_code = pdb_read_buf_get(compared_peer_id,
Jonathan Austin 0:bc2961fa1ef0 297 PM_PEER_DATA_ID_BONDING,
Jonathan Austin 0:bc2961fa1ef0 298 &compared_data,
Jonathan Austin 0:bc2961fa1ef0 299 NULL);
Jonathan Austin 0:bc2961fa1ef0 300 if (err_code == NRF_SUCCESS &&
Jonathan Austin 0:bc2961fa1ef0 301 im_address_resolve(&ble_evt->evt.gap_evt.params.connected.peer_addr,
Jonathan Austin 0:bc2961fa1ef0 302 &compared_data.data.p_bonding_data->peer_id.id_info)
Jonathan Austin 0:bc2961fa1ef0 303 )
Jonathan Austin 0:bc2961fa1ef0 304 {
Jonathan Austin 0:bc2961fa1ef0 305 bonded_matching_peer_id = compared_peer_id;
Jonathan Austin 0:bc2961fa1ef0 306 }
Jonathan Austin 0:bc2961fa1ef0 307 break;
Jonathan Austin 0:bc2961fa1ef0 308
Jonathan Austin 0:bc2961fa1ef0 309 case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE:
Jonathan Austin 0:bc2961fa1ef0 310 // Should not happen.
Jonathan Austin 0:bc2961fa1ef0 311 break;
Jonathan Austin 0:bc2961fa1ef0 312
Jonathan Austin 0:bc2961fa1ef0 313 default:
Jonathan Austin 0:bc2961fa1ef0 314 break;
Jonathan Austin 0:bc2961fa1ef0 315 }
Jonathan Austin 0:bc2961fa1ef0 316 compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
Jonathan Austin 0:bc2961fa1ef0 317 }
Jonathan Austin 0:bc2961fa1ef0 318 }
Jonathan Austin 0:bc2961fa1ef0 319 new_connection(ble_evt->evt.gap_evt.conn_handle, &ble_evt->evt.gap_evt.params.connected.peer_addr);
Jonathan Austin 0:bc2961fa1ef0 320
Jonathan Austin 0:bc2961fa1ef0 321 if (bonded_matching_peer_id != PM_PEER_ID_INVALID)
Jonathan Austin 0:bc2961fa1ef0 322 {
Jonathan Austin 0:bc2961fa1ef0 323 im_new_peer_id(ble_evt->evt.gap_evt.conn_handle, bonded_matching_peer_id);
Jonathan Austin 0:bc2961fa1ef0 324
Jonathan Austin 0:bc2961fa1ef0 325 // Send a bonded peer event
Jonathan Austin 0:bc2961fa1ef0 326 im_evt_t im_evt;
Jonathan Austin 0:bc2961fa1ef0 327 im_evt.conn_handle = ble_evt->evt.gap_evt.conn_handle;
Jonathan Austin 0:bc2961fa1ef0 328 im_evt.evt_id = IM_EVT_BONDED_PEER_CONNECTED;
Jonathan Austin 0:bc2961fa1ef0 329 evt_send(&im_evt);
Jonathan Austin 0:bc2961fa1ef0 330 }
Jonathan Austin 0:bc2961fa1ef0 331 }
Jonathan Austin 0:bc2961fa1ef0 332 }
Jonathan Austin 0:bc2961fa1ef0 333 }
Jonathan Austin 0:bc2961fa1ef0 334
Jonathan Austin 0:bc2961fa1ef0 335
Jonathan Austin 0:bc2961fa1ef0 336 /**@brief Function to compare two sets of bonding data to check if they belong to the same device.
Jonathan Austin 0:bc2961fa1ef0 337 * @note Invalid irks will never match even though they are identical.
Jonathan Austin 0:bc2961fa1ef0 338 *
Jonathan Austin 0:bc2961fa1ef0 339 * @param[in] p_bonding_data1 First bonding data for comparison
Jonathan Austin 0:bc2961fa1ef0 340 * @param[in] p_bonding_data2 Second bonding data for comparison
Jonathan Austin 0:bc2961fa1ef0 341 *
Jonathan Austin 0:bc2961fa1ef0 342 * @return True if the input matches, false if it does not.
Jonathan Austin 0:bc2961fa1ef0 343 */
Jonathan Austin 0:bc2961fa1ef0 344 bool is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1,
Jonathan Austin 0:bc2961fa1ef0 345 pm_peer_data_bonding_t const * p_bonding_data2)
Jonathan Austin 0:bc2961fa1ef0 346 {
Jonathan Austin 0:bc2961fa1ef0 347 bool valid_irk = is_valid_irk(&p_bonding_data1->peer_id.id_info);
Jonathan Austin 0:bc2961fa1ef0 348 bool duplicate_irk = valid_irk &&
Jonathan Austin 0:bc2961fa1ef0 349 (memcmp(p_bonding_data1->peer_id.id_info.irk,
Jonathan Austin 0:bc2961fa1ef0 350 p_bonding_data2->peer_id.id_info.irk,
Jonathan Austin 0:bc2961fa1ef0 351 BLE_GAP_SEC_KEY_LEN) == 0
Jonathan Austin 0:bc2961fa1ef0 352 );
Jonathan Austin 0:bc2961fa1ef0 353 bool duplicate_addr = addr_compare(&p_bonding_data1->peer_id.id_addr_info,
Jonathan Austin 0:bc2961fa1ef0 354 &p_bonding_data2->peer_id.id_addr_info
Jonathan Austin 0:bc2961fa1ef0 355 );
Jonathan Austin 0:bc2961fa1ef0 356 return duplicate_irk || duplicate_addr;
Jonathan Austin 0:bc2961fa1ef0 357 }
Jonathan Austin 0:bc2961fa1ef0 358
Jonathan Austin 0:bc2961fa1ef0 359
Jonathan Austin 0:bc2961fa1ef0 360 /**@brief Event handler for events from the peer_database module.
Jonathan Austin 0:bc2961fa1ef0 361 *
Jonathan Austin 0:bc2961fa1ef0 362 * @param[in] p_event The event that has happend with peer id and flags.
Jonathan Austin 0:bc2961fa1ef0 363 */
Jonathan Austin 0:bc2961fa1ef0 364 static void pdb_evt_handler(pdb_evt_t const * p_event)
Jonathan Austin 0:bc2961fa1ef0 365 {
Jonathan Austin 0:bc2961fa1ef0 366 ret_code_t err_code;
Jonathan Austin 0:bc2961fa1ef0 367 if ((p_event != NULL) && (p_event->evt_id == PDB_EVT_WRITE_BUF_STORED))
Jonathan Austin 0:bc2961fa1ef0 368 {
Jonathan Austin 0:bc2961fa1ef0 369 // If new data about peer id has been stored it is compared to other peers peer ids in
Jonathan Austin 0:bc2961fa1ef0 370 // search of duplicates.
Jonathan Austin 0:bc2961fa1ef0 371 if (p_event->data_id == PM_PEER_DATA_ID_BONDING)
Jonathan Austin 0:bc2961fa1ef0 372 {
Jonathan Austin 0:bc2961fa1ef0 373 pm_peer_data_flash_t written_data;
Jonathan Austin 0:bc2961fa1ef0 374 err_code = pdb_read_buf_get(p_event->peer_id, PM_PEER_DATA_ID_BONDING, &written_data, NULL);
Jonathan Austin 0:bc2961fa1ef0 375 if (err_code == NRF_SUCCESS)
Jonathan Austin 0:bc2961fa1ef0 376 {
Jonathan Austin 0:bc2961fa1ef0 377 pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
Jonathan Austin 0:bc2961fa1ef0 378 while (compared_peer_id != PM_PEER_ID_INVALID)
Jonathan Austin 0:bc2961fa1ef0 379 {
Jonathan Austin 0:bc2961fa1ef0 380 pm_peer_data_flash_t compared_data;
Jonathan Austin 0:bc2961fa1ef0 381 err_code = pdb_read_buf_get(compared_peer_id,
Jonathan Austin 0:bc2961fa1ef0 382 PM_PEER_DATA_ID_BONDING,
Jonathan Austin 0:bc2961fa1ef0 383 &compared_data,
Jonathan Austin 0:bc2961fa1ef0 384 NULL);
Jonathan Austin 0:bc2961fa1ef0 385 if ( err_code == NRF_SUCCESS &&
Jonathan Austin 0:bc2961fa1ef0 386 p_event->peer_id != compared_peer_id &&
Jonathan Austin 0:bc2961fa1ef0 387 is_duplicate_bonding_data(written_data.data.p_bonding_data,
Jonathan Austin 0:bc2961fa1ef0 388 compared_data.data.p_bonding_data)
Jonathan Austin 0:bc2961fa1ef0 389 )
Jonathan Austin 0:bc2961fa1ef0 390 {
Jonathan Austin 0:bc2961fa1ef0 391 im_evt_t im_evt;
Jonathan Austin 0:bc2961fa1ef0 392 im_evt.conn_handle = im_conn_handle_get(p_event->peer_id);
Jonathan Austin 0:bc2961fa1ef0 393 im_evt.evt_id = IM_EVT_DUPLICATE_ID;
Jonathan Austin 0:bc2961fa1ef0 394 im_evt.params.duplicate_id.peer_id_1 = p_event->peer_id;
Jonathan Austin 0:bc2961fa1ef0 395 im_evt.params.duplicate_id.peer_id_2 = compared_peer_id;
Jonathan Austin 0:bc2961fa1ef0 396 evt_send(&im_evt);
Jonathan Austin 0:bc2961fa1ef0 397 }
Jonathan Austin 0:bc2961fa1ef0 398 compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
Jonathan Austin 0:bc2961fa1ef0 399 }
Jonathan Austin 0:bc2961fa1ef0 400 }
Jonathan Austin 0:bc2961fa1ef0 401 }
Jonathan Austin 0:bc2961fa1ef0 402 }
Jonathan Austin 0:bc2961fa1ef0 403 }
Jonathan Austin 0:bc2961fa1ef0 404
Jonathan Austin 0:bc2961fa1ef0 405
Jonathan Austin 0:bc2961fa1ef0 406 ret_code_t im_register(im_evt_handler_t evt_handler)
Jonathan Austin 0:bc2961fa1ef0 407 {
Jonathan Austin 0:bc2961fa1ef0 408 VERIFY_PARAM_NOT_NULL(evt_handler);
Jonathan Austin 0:bc2961fa1ef0 409 ret_code_t err_code = NRF_SUCCESS;
Jonathan Austin 0:bc2961fa1ef0 410
Jonathan Austin 0:bc2961fa1ef0 411 if (!MODULE_INITIALIZED)
Jonathan Austin 0:bc2961fa1ef0 412 {
Jonathan Austin 0:bc2961fa1ef0 413 internal_state_reset();
Jonathan Austin 0:bc2961fa1ef0 414 m_im.conn_state_user_flag_id = ble_conn_state_user_flag_acquire();
Jonathan Austin 0:bc2961fa1ef0 415 if (m_im.conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID)
Jonathan Austin 0:bc2961fa1ef0 416 {
Jonathan Austin 0:bc2961fa1ef0 417 err_code = NRF_ERROR_NO_MEM;
Jonathan Austin 0:bc2961fa1ef0 418 }
Jonathan Austin 0:bc2961fa1ef0 419 else
Jonathan Austin 0:bc2961fa1ef0 420 {
Jonathan Austin 0:bc2961fa1ef0 421 err_code = pdb_register(pdb_evt_handler);
Jonathan Austin 0:bc2961fa1ef0 422 }
Jonathan Austin 0:bc2961fa1ef0 423 }
Jonathan Austin 0:bc2961fa1ef0 424 if (err_code == NRF_SUCCESS)
Jonathan Austin 0:bc2961fa1ef0 425 {
Jonathan Austin 0:bc2961fa1ef0 426 if ((m_im.n_registrants < MAX_REGISTRANTS))
Jonathan Austin 0:bc2961fa1ef0 427 {
Jonathan Austin 0:bc2961fa1ef0 428 m_im.evt_handlers[m_im.n_registrants++] = evt_handler;
Jonathan Austin 0:bc2961fa1ef0 429 }
Jonathan Austin 0:bc2961fa1ef0 430 else
Jonathan Austin 0:bc2961fa1ef0 431 {
Jonathan Austin 0:bc2961fa1ef0 432 err_code = NRF_ERROR_NO_MEM;
Jonathan Austin 0:bc2961fa1ef0 433 }
Jonathan Austin 0:bc2961fa1ef0 434 }
Jonathan Austin 0:bc2961fa1ef0 435 return err_code;
Jonathan Austin 0:bc2961fa1ef0 436 }
Jonathan Austin 0:bc2961fa1ef0 437
Jonathan Austin 0:bc2961fa1ef0 438
Jonathan Austin 0:bc2961fa1ef0 439 pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle)
Jonathan Austin 0:bc2961fa1ef0 440 {
Jonathan Austin 0:bc2961fa1ef0 441 uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
Jonathan Austin 0:bc2961fa1ef0 442
Jonathan Austin 0:bc2961fa1ef0 443 if (MODULE_INITIALIZED && (conn_index != IM_NO_INVALID_CONN_HANDLES))
Jonathan Austin 0:bc2961fa1ef0 444 {
Jonathan Austin 0:bc2961fa1ef0 445 return m_im.connections[conn_index].peer_id;
Jonathan Austin 0:bc2961fa1ef0 446 }
Jonathan Austin 0:bc2961fa1ef0 447
Jonathan Austin 0:bc2961fa1ef0 448 return PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 449 }
Jonathan Austin 0:bc2961fa1ef0 450
Jonathan Austin 0:bc2961fa1ef0 451
Jonathan Austin 0:bc2961fa1ef0 452 ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr)
Jonathan Austin 0:bc2961fa1ef0 453 {
Jonathan Austin 0:bc2961fa1ef0 454 VERIFY_MODULE_INITIALIZED();
Jonathan Austin 0:bc2961fa1ef0 455 VERIFY_PARAM_NOT_NULL(p_ble_addr);
Jonathan Austin 0:bc2961fa1ef0 456
Jonathan Austin 0:bc2961fa1ef0 457 uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
Jonathan Austin 0:bc2961fa1ef0 458 if (conn_index != IM_NO_INVALID_CONN_HANDLES)
Jonathan Austin 0:bc2961fa1ef0 459 {
Jonathan Austin 0:bc2961fa1ef0 460 *p_ble_addr = m_im.connections[conn_index].peer_address;
Jonathan Austin 0:bc2961fa1ef0 461 return NRF_SUCCESS;
Jonathan Austin 0:bc2961fa1ef0 462 }
Jonathan Austin 0:bc2961fa1ef0 463
Jonathan Austin 0:bc2961fa1ef0 464 return NRF_ERROR_NOT_FOUND;
Jonathan Austin 0:bc2961fa1ef0 465 }
Jonathan Austin 0:bc2961fa1ef0 466
Jonathan Austin 0:bc2961fa1ef0 467
Jonathan Austin 0:bc2961fa1ef0 468 /**@brief Function for comparing two master ids
Jonathan Austin 0:bc2961fa1ef0 469 * @note Two invalid master IDs will not match.
Jonathan Austin 0:bc2961fa1ef0 470 *
Jonathan Austin 0:bc2961fa1ef0 471 * @param[in] p_master_id1 First master id for comparison
Jonathan Austin 0:bc2961fa1ef0 472 * @param[in] p_master_id2 Second master id for comparison
Jonathan Austin 0:bc2961fa1ef0 473 *
Jonathan Austin 0:bc2961fa1ef0 474 * @return True if the input matches, false if it does not.
Jonathan Austin 0:bc2961fa1ef0 475 */
Jonathan Austin 0:bc2961fa1ef0 476 bool master_id_compare(ble_gap_master_id_t const * p_master_id1,
Jonathan Austin 0:bc2961fa1ef0 477 ble_gap_master_id_t const * p_master_id2)
Jonathan Austin 0:bc2961fa1ef0 478 {
Jonathan Austin 0:bc2961fa1ef0 479 if(!im_master_id_is_valid(p_master_id1))
Jonathan Austin 0:bc2961fa1ef0 480 {
Jonathan Austin 0:bc2961fa1ef0 481 return false;
Jonathan Austin 0:bc2961fa1ef0 482 }
Jonathan Austin 0:bc2961fa1ef0 483 if (p_master_id1->ediv != p_master_id2->ediv)
Jonathan Austin 0:bc2961fa1ef0 484 {
Jonathan Austin 0:bc2961fa1ef0 485 return false;
Jonathan Austin 0:bc2961fa1ef0 486 }
Jonathan Austin 0:bc2961fa1ef0 487 return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0);
Jonathan Austin 0:bc2961fa1ef0 488 }
Jonathan Austin 0:bc2961fa1ef0 489
Jonathan Austin 0:bc2961fa1ef0 490
Jonathan Austin 0:bc2961fa1ef0 491 pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t * p_master_id)
Jonathan Austin 0:bc2961fa1ef0 492 {
Jonathan Austin 0:bc2961fa1ef0 493 ret_code_t err_code;
Jonathan Austin 0:bc2961fa1ef0 494 // For each stored peer, check if the master_id match p_master_id
Jonathan Austin 0:bc2961fa1ef0 495 pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
Jonathan Austin 0:bc2961fa1ef0 496 while (compared_peer_id != PM_PEER_ID_INVALID)
Jonathan Austin 0:bc2961fa1ef0 497 {
Jonathan Austin 0:bc2961fa1ef0 498 pm_peer_data_flash_t compared_data;
Jonathan Austin 0:bc2961fa1ef0 499 ble_gap_master_id_t const * p_compared_master_id;
Jonathan Austin 0:bc2961fa1ef0 500
Jonathan Austin 0:bc2961fa1ef0 501 err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
Jonathan Austin 0:bc2961fa1ef0 502 if (err_code == NRF_SUCCESS)
Jonathan Austin 0:bc2961fa1ef0 503 {
Jonathan Austin 0:bc2961fa1ef0 504 p_compared_master_id = &compared_data.data.p_bonding_data->own_ltk.master_id;
Jonathan Austin 0:bc2961fa1ef0 505 if (compared_data.data.p_bonding_data->own_role == BLE_GAP_ROLE_CENTRAL)
Jonathan Austin 0:bc2961fa1ef0 506 {
Jonathan Austin 0:bc2961fa1ef0 507 p_compared_master_id = &compared_data.data.p_bonding_data->peer_ltk.master_id;
Jonathan Austin 0:bc2961fa1ef0 508 }
Jonathan Austin 0:bc2961fa1ef0 509 if (master_id_compare(p_master_id, p_compared_master_id))
Jonathan Austin 0:bc2961fa1ef0 510 {
Jonathan Austin 0:bc2961fa1ef0 511 // If a matching master_id is found return the peer_id
Jonathan Austin 0:bc2961fa1ef0 512 return compared_peer_id;
Jonathan Austin 0:bc2961fa1ef0 513 }
Jonathan Austin 0:bc2961fa1ef0 514 }
Jonathan Austin 0:bc2961fa1ef0 515 compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
Jonathan Austin 0:bc2961fa1ef0 516 }
Jonathan Austin 0:bc2961fa1ef0 517 // If no matching master_id is found return the PM_PEER_ID_INVALID
Jonathan Austin 0:bc2961fa1ef0 518 return PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 519 }
Jonathan Austin 0:bc2961fa1ef0 520
Jonathan Austin 0:bc2961fa1ef0 521
Jonathan Austin 0:bc2961fa1ef0 522 pm_peer_id_t im_peer_id_get_by_irk_match_idx(uint8_t irk_match_idx)
Jonathan Austin 0:bc2961fa1ef0 523 {
Jonathan Austin 0:bc2961fa1ef0 524 // Verify that the requested idx is within the list
Jonathan Austin 0:bc2961fa1ef0 525 if (irk_match_idx < m_im.n_whitelist_peer_ids)
Jonathan Austin 0:bc2961fa1ef0 526 {
Jonathan Austin 0:bc2961fa1ef0 527 // Return the peer_id from the white list
Jonathan Austin 0:bc2961fa1ef0 528 return m_im.whitelist_peer_ids[irk_match_idx];
Jonathan Austin 0:bc2961fa1ef0 529 }
Jonathan Austin 0:bc2961fa1ef0 530 else
Jonathan Austin 0:bc2961fa1ef0 531 {
Jonathan Austin 0:bc2961fa1ef0 532 // Return PM_PEER_ID_INVALID to indicate that there was no peer with the requested idx
Jonathan Austin 0:bc2961fa1ef0 533 return PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 534 }
Jonathan Austin 0:bc2961fa1ef0 535 }
Jonathan Austin 0:bc2961fa1ef0 536
Jonathan Austin 0:bc2961fa1ef0 537
Jonathan Austin 0:bc2961fa1ef0 538 uint16_t im_conn_handle_get(pm_peer_id_t peer_id)
Jonathan Austin 0:bc2961fa1ef0 539 {
Jonathan Austin 0:bc2961fa1ef0 540 for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
Jonathan Austin 0:bc2961fa1ef0 541 {
Jonathan Austin 0:bc2961fa1ef0 542 if (peer_id == m_im.connections[i].peer_id)
Jonathan Austin 0:bc2961fa1ef0 543 {
Jonathan Austin 0:bc2961fa1ef0 544 return m_im.connections[i].conn_handle;
Jonathan Austin 0:bc2961fa1ef0 545 }
Jonathan Austin 0:bc2961fa1ef0 546 }
Jonathan Austin 0:bc2961fa1ef0 547 return BLE_CONN_HANDLE_INVALID;
Jonathan Austin 0:bc2961fa1ef0 548 }
Jonathan Austin 0:bc2961fa1ef0 549
Jonathan Austin 0:bc2961fa1ef0 550
Jonathan Austin 0:bc2961fa1ef0 551 bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id)
Jonathan Austin 0:bc2961fa1ef0 552 {
Jonathan Austin 0:bc2961fa1ef0 553
Jonathan Austin 0:bc2961fa1ef0 554 if (p_master_id->ediv != 0)
Jonathan Austin 0:bc2961fa1ef0 555 {
Jonathan Austin 0:bc2961fa1ef0 556 return true;
Jonathan Austin 0:bc2961fa1ef0 557 }
Jonathan Austin 0:bc2961fa1ef0 558 for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++)
Jonathan Austin 0:bc2961fa1ef0 559 {
Jonathan Austin 0:bc2961fa1ef0 560 if (p_master_id->rand[i] != 0)
Jonathan Austin 0:bc2961fa1ef0 561 {
Jonathan Austin 0:bc2961fa1ef0 562 return true;
Jonathan Austin 0:bc2961fa1ef0 563 }
Jonathan Austin 0:bc2961fa1ef0 564 }
Jonathan Austin 0:bc2961fa1ef0 565 return false;
Jonathan Austin 0:bc2961fa1ef0 566 }
Jonathan Austin 0:bc2961fa1ef0 567
Jonathan Austin 0:bc2961fa1ef0 568
Jonathan Austin 0:bc2961fa1ef0 569 void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id)
Jonathan Austin 0:bc2961fa1ef0 570 {
Jonathan Austin 0:bc2961fa1ef0 571 uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
Jonathan Austin 0:bc2961fa1ef0 572 if (conn_index != IM_NO_INVALID_CONN_HANDLES)
Jonathan Austin 0:bc2961fa1ef0 573 {
Jonathan Austin 0:bc2961fa1ef0 574 m_im.connections[conn_index].peer_id = peer_id;
Jonathan Austin 0:bc2961fa1ef0 575 }
Jonathan Austin 0:bc2961fa1ef0 576 }
Jonathan Austin 0:bc2961fa1ef0 577
Jonathan Austin 0:bc2961fa1ef0 578
Jonathan Austin 0:bc2961fa1ef0 579 ret_code_t im_wlist_create(pm_peer_id_t * p_peer_ids,
Jonathan Austin 0:bc2961fa1ef0 580 uint8_t n_peer_ids,
Jonathan Austin 0:bc2961fa1ef0 581 ble_gap_whitelist_t * p_whitelist)
Jonathan Austin 0:bc2961fa1ef0 582 {
Jonathan Austin 0:bc2961fa1ef0 583 VERIFY_MODULE_INITIALIZED();
Jonathan Austin 0:bc2961fa1ef0 584 VERIFY_PARAM_NOT_NULL(p_whitelist);
Jonathan Austin 0:bc2961fa1ef0 585 ret_code_t err_code;
Jonathan Austin 0:bc2961fa1ef0 586 p_whitelist->addr_count = 0;
Jonathan Austin 0:bc2961fa1ef0 587 p_whitelist->irk_count = 0;
Jonathan Austin 0:bc2961fa1ef0 588 m_im.n_whitelist_peer_ids = 0;
Jonathan Austin 0:bc2961fa1ef0 589 for (uint32_t peer_index = 0; peer_index < n_peer_ids; peer_index++)
Jonathan Austin 0:bc2961fa1ef0 590 {
Jonathan Austin 0:bc2961fa1ef0 591 bool peer_connected = false;
Jonathan Austin 0:bc2961fa1ef0 592 for (uint32_t conn_index = 0; conn_index < IM_MAX_CONN_HANDLES; conn_index++)
Jonathan Austin 0:bc2961fa1ef0 593 {
Jonathan Austin 0:bc2961fa1ef0 594 if (p_peer_ids[peer_index] == m_im.connections[conn_index].peer_id &&
Jonathan Austin 0:bc2961fa1ef0 595 ble_conn_state_user_flag_get(m_im.connections[conn_index].conn_handle, m_im.conn_state_user_flag_id)
Jonathan Austin 0:bc2961fa1ef0 596 )
Jonathan Austin 0:bc2961fa1ef0 597 {
Jonathan Austin 0:bc2961fa1ef0 598 peer_connected = true;
Jonathan Austin 0:bc2961fa1ef0 599 break;
Jonathan Austin 0:bc2961fa1ef0 600 }
Jonathan Austin 0:bc2961fa1ef0 601 }
Jonathan Austin 0:bc2961fa1ef0 602 if (!peer_connected)
Jonathan Austin 0:bc2961fa1ef0 603 {
Jonathan Austin 0:bc2961fa1ef0 604 pm_peer_data_flash_t peer_data;
Jonathan Austin 0:bc2961fa1ef0 605 err_code = pdb_read_buf_get(p_peer_ids[peer_index], PM_PEER_DATA_ID_BONDING, &peer_data, NULL);
Jonathan Austin 0:bc2961fa1ef0 606 if (err_code == NRF_ERROR_INVALID_PARAM || err_code == NRF_ERROR_NOT_FOUND)
Jonathan Austin 0:bc2961fa1ef0 607 {
Jonathan Austin 0:bc2961fa1ef0 608 return NRF_ERROR_INVALID_PARAM;
Jonathan Austin 0:bc2961fa1ef0 609 }
Jonathan Austin 0:bc2961fa1ef0 610 if (p_whitelist->pp_addrs != NULL &&
Jonathan Austin 0:bc2961fa1ef0 611 peer_data.data.p_bonding_data->peer_id.id_addr_info.addr_type
Jonathan Austin 0:bc2961fa1ef0 612 != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE &&
Jonathan Austin 0:bc2961fa1ef0 613 peer_data.data.p_bonding_data->peer_id.id_addr_info.addr_type
Jonathan Austin 0:bc2961fa1ef0 614 != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
Jonathan Austin 0:bc2961fa1ef0 615 )
Jonathan Austin 0:bc2961fa1ef0 616 {
Jonathan Austin 0:bc2961fa1ef0 617 memcpy(m_im.whitelist_addrs[peer_index].addr,
Jonathan Austin 0:bc2961fa1ef0 618 peer_data.data.p_bonding_data->peer_id.id_addr_info.addr,
Jonathan Austin 0:bc2961fa1ef0 619 BLE_GAP_ADDR_LEN
Jonathan Austin 0:bc2961fa1ef0 620 );
Jonathan Austin 0:bc2961fa1ef0 621 m_im.whitelist_addrs[peer_index].addr_type =
Jonathan Austin 0:bc2961fa1ef0 622 peer_data.data.p_bonding_data->peer_id.id_addr_info.addr_type;
Jonathan Austin 0:bc2961fa1ef0 623 p_whitelist->pp_addrs[peer_index] = &m_im.whitelist_addrs[peer_index];
Jonathan Austin 0:bc2961fa1ef0 624 p_whitelist->addr_count++;
Jonathan Austin 0:bc2961fa1ef0 625 }
Jonathan Austin 0:bc2961fa1ef0 626 if (p_whitelist->pp_irks != NULL &&
Jonathan Austin 0:bc2961fa1ef0 627 is_valid_irk(&(peer_data.data.p_bonding_data->peer_id.id_info))
Jonathan Austin 0:bc2961fa1ef0 628 )
Jonathan Austin 0:bc2961fa1ef0 629 {
Jonathan Austin 0:bc2961fa1ef0 630 memcpy(m_im.whitelist_irks[peer_index].irk,
Jonathan Austin 0:bc2961fa1ef0 631 peer_data.data.p_bonding_data->peer_id.id_info.irk,
Jonathan Austin 0:bc2961fa1ef0 632 BLE_GAP_SEC_KEY_LEN
Jonathan Austin 0:bc2961fa1ef0 633 );
Jonathan Austin 0:bc2961fa1ef0 634 p_whitelist->pp_irks[peer_index] = &m_im.whitelist_irks[peer_index];
Jonathan Austin 0:bc2961fa1ef0 635 p_whitelist->irk_count++;
Jonathan Austin 0:bc2961fa1ef0 636 m_im.whitelist_peer_ids[peer_index] = p_peer_ids[peer_index];
Jonathan Austin 0:bc2961fa1ef0 637 m_im.n_whitelist_peer_ids++;
Jonathan Austin 0:bc2961fa1ef0 638 }
Jonathan Austin 0:bc2961fa1ef0 639 }
Jonathan Austin 0:bc2961fa1ef0 640 }
Jonathan Austin 0:bc2961fa1ef0 641 return NRF_SUCCESS;
Jonathan Austin 0:bc2961fa1ef0 642 }
Jonathan Austin 0:bc2961fa1ef0 643
Jonathan Austin 0:bc2961fa1ef0 644
Jonathan Austin 0:bc2961fa1ef0 645 ret_code_t im_wlist_set(ble_gap_whitelist_t * p_whitelist)
Jonathan Austin 0:bc2961fa1ef0 646 {
Jonathan Austin 0:bc2961fa1ef0 647 pm_peer_id_t new_whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
Jonathan Austin 0:bc2961fa1ef0 648 uint32_t n_new_whitelist_peer_ids = 0;
Jonathan Austin 0:bc2961fa1ef0 649 VERIFY_PARAM_NOT_NULL(p_whitelist);
Jonathan Austin 0:bc2961fa1ef0 650 for (uint32_t i = 0; i < BLE_GAP_WHITELIST_IRK_MAX_COUNT; i++)
Jonathan Austin 0:bc2961fa1ef0 651 {
Jonathan Austin 0:bc2961fa1ef0 652 new_whitelist_peer_ids[i] = PM_PEER_ID_INVALID;
Jonathan Austin 0:bc2961fa1ef0 653 }
Jonathan Austin 0:bc2961fa1ef0 654 pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
Jonathan Austin 0:bc2961fa1ef0 655 while (compared_peer_id != PM_PEER_ID_INVALID)
Jonathan Austin 0:bc2961fa1ef0 656 {
Jonathan Austin 0:bc2961fa1ef0 657 pm_peer_data_flash_t compared_data;
Jonathan Austin 0:bc2961fa1ef0 658 pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
Jonathan Austin 0:bc2961fa1ef0 659 for (uint32_t i = 0; i < p_whitelist->irk_count; i++)
Jonathan Austin 0:bc2961fa1ef0 660 {
Jonathan Austin 0:bc2961fa1ef0 661 bool valid_irk = is_valid_irk(&compared_data.data.p_bonding_data->peer_id.id_info);
Jonathan Austin 0:bc2961fa1ef0 662 bool duplicate_irk = valid_irk &&
Jonathan Austin 0:bc2961fa1ef0 663 (memcmp(p_whitelist->pp_irks[i]->irk,
Jonathan Austin 0:bc2961fa1ef0 664 compared_data.data.p_bonding_data->peer_id.id_info.irk,
Jonathan Austin 0:bc2961fa1ef0 665 BLE_GAP_SEC_KEY_LEN) == 0
Jonathan Austin 0:bc2961fa1ef0 666 );
Jonathan Austin 0:bc2961fa1ef0 667 if (duplicate_irk)
Jonathan Austin 0:bc2961fa1ef0 668 {
Jonathan Austin 0:bc2961fa1ef0 669 new_whitelist_peer_ids[i] = compared_peer_id;
Jonathan Austin 0:bc2961fa1ef0 670 n_new_whitelist_peer_ids++;
Jonathan Austin 0:bc2961fa1ef0 671 }
Jonathan Austin 0:bc2961fa1ef0 672 }
Jonathan Austin 0:bc2961fa1ef0 673 compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
Jonathan Austin 0:bc2961fa1ef0 674 }
Jonathan Austin 0:bc2961fa1ef0 675 if (n_new_whitelist_peer_ids != p_whitelist->irk_count)
Jonathan Austin 0:bc2961fa1ef0 676 {
Jonathan Austin 0:bc2961fa1ef0 677 return NRF_ERROR_NOT_FOUND;
Jonathan Austin 0:bc2961fa1ef0 678 }
Jonathan Austin 0:bc2961fa1ef0 679 else
Jonathan Austin 0:bc2961fa1ef0 680 {
Jonathan Austin 0:bc2961fa1ef0 681 for (uint32_t i = 0; i < n_new_whitelist_peer_ids; i++)
Jonathan Austin 0:bc2961fa1ef0 682 {
Jonathan Austin 0:bc2961fa1ef0 683 m_im.whitelist_peer_ids[i] = new_whitelist_peer_ids[i];
Jonathan Austin 0:bc2961fa1ef0 684 }
Jonathan Austin 0:bc2961fa1ef0 685 m_im.n_whitelist_peer_ids = n_new_whitelist_peer_ids;
Jonathan Austin 0:bc2961fa1ef0 686 return NRF_SUCCESS;
Jonathan Austin 0:bc2961fa1ef0 687 }
Jonathan Austin 0:bc2961fa1ef0 688 }
Jonathan Austin 0:bc2961fa1ef0 689
Jonathan Austin 0:bc2961fa1ef0 690
Jonathan Austin 0:bc2961fa1ef0 691 /**@brief Function for calculating the ah() hash function described in Bluetooth core specification
Jonathan Austin 0:bc2961fa1ef0 692 * 4.2 section 3.H.2.2.2.
Jonathan Austin 0:bc2961fa1ef0 693 *
Jonathan Austin 0:bc2961fa1ef0 694 * @detail BLE uses a hash function to calculate the first half of a resolvable address
Jonathan Austin 0:bc2961fa1ef0 695 * from the second half of the address and an irk. This function will use the ECB
Jonathan Austin 0:bc2961fa1ef0 696 * periferal to hash these data acording to the Bluetooth core specification.
Jonathan Austin 0:bc2961fa1ef0 697 *
Jonathan Austin 0:bc2961fa1ef0 698 * @note The ECB expect little endian input and output.
Jonathan Austin 0:bc2961fa1ef0 699 * This function expect big endian and will reverse the data as necessary.
Jonathan Austin 0:bc2961fa1ef0 700 *
Jonathan Austin 0:bc2961fa1ef0 701 * @param[in] p_k The key used in the hash function.
Jonathan Austin 0:bc2961fa1ef0 702 * For address resolution this is should be the irk.
Jonathan Austin 0:bc2961fa1ef0 703 * The array must have a length of 16.
Jonathan Austin 0:bc2961fa1ef0 704 * @param[in] p_r The rand used in the hash function. For generating a new address
Jonathan Austin 0:bc2961fa1ef0 705 * this would be a random number. For resolving a resolvable address
Jonathan Austin 0:bc2961fa1ef0 706 * this would be the last half of the address being resolved.
Jonathan Austin 0:bc2961fa1ef0 707 * The array must have a length of 3.
Jonathan Austin 0:bc2961fa1ef0 708 * @param[out] p_local_hash The result of the hash operation. For address resolution this
Jonathan Austin 0:bc2961fa1ef0 709 * will match the first half of the address being resolved if and only
Jonathan Austin 0:bc2961fa1ef0 710 * if the irk used in the hash function is the same one used to generate
Jonathan Austin 0:bc2961fa1ef0 711 * the address.
Jonathan Austin 0:bc2961fa1ef0 712 * The array must have a length of 16.
Jonathan Austin 0:bc2961fa1ef0 713 */
Jonathan Austin 0:bc2961fa1ef0 714 void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash)
Jonathan Austin 0:bc2961fa1ef0 715 {
Jonathan Austin 0:bc2961fa1ef0 716 nrf_ecb_hal_data_t ecb_hal_data;
Jonathan Austin 0:bc2961fa1ef0 717 for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++)
Jonathan Austin 0:bc2961fa1ef0 718 {
Jonathan Austin 0:bc2961fa1ef0 719 ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i];
Jonathan Austin 0:bc2961fa1ef0 720 }
Jonathan Austin 0:bc2961fa1ef0 721 memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH);
Jonathan Austin 0:bc2961fa1ef0 722
Jonathan Austin 0:bc2961fa1ef0 723 for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++)
Jonathan Austin 0:bc2961fa1ef0 724 {
Jonathan Austin 0:bc2961fa1ef0 725 ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i];
Jonathan Austin 0:bc2961fa1ef0 726 }
Jonathan Austin 0:bc2961fa1ef0 727
Jonathan Austin 0:bc2961fa1ef0 728 sd_ecb_block_encrypt(&ecb_hal_data);
Jonathan Austin 0:bc2961fa1ef0 729
Jonathan Austin 0:bc2961fa1ef0 730 for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++)
Jonathan Austin 0:bc2961fa1ef0 731 {
Jonathan Austin 0:bc2961fa1ef0 732 p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i];
Jonathan Austin 0:bc2961fa1ef0 733 }
Jonathan Austin 0:bc2961fa1ef0 734 }
Jonathan Austin 0:bc2961fa1ef0 735
Jonathan Austin 0:bc2961fa1ef0 736
Jonathan Austin 0:bc2961fa1ef0 737 bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
Jonathan Austin 0:bc2961fa1ef0 738 {
Jonathan Austin 0:bc2961fa1ef0 739 if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
Jonathan Austin 0:bc2961fa1ef0 740 {
Jonathan Austin 0:bc2961fa1ef0 741 return false;
Jonathan Austin 0:bc2961fa1ef0 742 }
Jonathan Austin 0:bc2961fa1ef0 743 uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH];
Jonathan Austin 0:bc2961fa1ef0 744 uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH];
Jonathan Austin 0:bc2961fa1ef0 745 uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH];
Jonathan Austin 0:bc2961fa1ef0 746 memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH);
Jonathan Austin 0:bc2961fa1ef0 747 memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH);
Jonathan Austin 0:bc2961fa1ef0 748 ah(p_irk->irk, prand, local_hash);
Jonathan Austin 0:bc2961fa1ef0 749
Jonathan Austin 0:bc2961fa1ef0 750 return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0);
Jonathan Austin 0:bc2961fa1ef0 751 }