Nordic stack and drivers for the mbed BLE API

Fork of nRF51822 by Nordic Semiconductor

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:39:43 2016 +0100
Revision:
640:c90ae1400bf2
Sync with bdab10dc0f90748b6989c8b577771bb403ca6bd8 from ARMmbed/mbed-os.

Who changed what in which revision?

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