Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
source/nordic_sdk/components/ble/peer_manager/id_manager.c@0:bc2961fa1ef0, 2016-04-06 (annotated)
- Committer:
- Jonathan Austin
- Date:
- Wed Apr 06 23:55:04 2016 +0100
- Revision:
- 0:bc2961fa1ef0
Synchronized with git rev 90647e3
Who changed what in which revision?
User | Revision | Line number | New 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 | } |