cvb
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 | } |