1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/bluetooth/addr.h>
9 #include <host/keys.h>
10 #include "mocks/conn.h"
11 #include "mocks/hci_core.h"
12 #include "mocks/keys_help_utils.h"
13 #include "mocks/hci_core_expects.h"
14 #include "testing_common_defs.h"
15
16 /* This LUT contains different combinations of ID and Address pairs */
17 extern const struct id_addr_pair testing_id_addr_pair_lut[CONFIG_BT_MAX_PAIRED];
18
19 /* This list holds returned references while filling keys pool */
20 extern struct bt_keys *returned_keys_refs[CONFIG_BT_MAX_PAIRED];
21
22 /* Pointer to the current set of oldest testing parameter */
23 struct id_addr_pair const *oldest_params_vector;
24
bt_unpair_custom_fake(uint8_t id,const bt_addr_le_t * addr)25 static int bt_unpair_custom_fake(uint8_t id, const bt_addr_le_t *addr)
26 {
27 struct bt_keys *keys = NULL;
28
29 /* Find the key slot with matched id and address */
30 keys = bt_keys_find_addr(id, addr);
31 if (keys) {
32 bt_keys_clear(keys);
33 }
34
35 /* This check is used here because bt_unpair() is called with a local variable address */
36 expect_single_call_bt_unpair(oldest_params_vector->id, oldest_params_vector->addr);
37
38 return 0;
39 }
40
bt_unpair_unreachable_custom_fake(uint8_t id,const bt_addr_le_t * addr)41 static int bt_unpair_unreachable_custom_fake(uint8_t id, const bt_addr_le_t *addr)
42 {
43 ARG_UNUSED(id);
44 ARG_UNUSED(addr);
45 zassert_unreachable("Unexpected call to 'bt_unpair()' occurred");
46 return 0;
47 }
48
bt_conn_foreach_key_slot_0_in_use_custom_fake(enum bt_conn_type type,bt_conn_foreach_cb func,void * data)49 static void bt_conn_foreach_key_slot_0_in_use_custom_fake(enum bt_conn_type type,
50 bt_conn_foreach_cb func, void *data)
51 {
52 struct bt_conn conn;
53
54 /* This will make the effect as if there is a disconnection */
55 conn.state = BT_CONN_DISCONNECTED;
56 conn.id = 0x9E;
57 func(&conn, data);
58
59 /* This will make the effect as if there is a connection with no key */
60 conn.state = BT_CONN_CONNECTED;
61 conn.id = 0xFF;
62 bt_addr_le_copy(&conn.le.dst, (const bt_addr_le_t *)BT_ADDR_LE_ANY);
63 bt_conn_get_dst_fake.return_val = &conn.le.dst;
64 func(&conn, data);
65
66 /* This will make the effect as if key at slot 0 is in use with a connection */
67 conn.state = BT_CONN_CONNECTED;
68 conn.id = testing_id_addr_pair_lut[0].id;
69 bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[0].addr);
70 bt_conn_get_dst_fake.return_val = &conn.le.dst;
71 func(&conn, data);
72 }
73
bt_conn_foreach_all_keys_in_use_custom_fake(enum bt_conn_type type,bt_conn_foreach_cb func,void * data)74 static void bt_conn_foreach_all_keys_in_use_custom_fake(enum bt_conn_type type,
75 bt_conn_foreach_cb func, void *data)
76 {
77 struct bt_conn conn;
78
79 /* This will make the effect as if key at slot 'x' is in use with a connection */
80 for (size_t i = 0; i < ARRAY_SIZE(testing_id_addr_pair_lut); i++) {
81 conn.state = BT_CONN_CONNECTED;
82 conn.id = testing_id_addr_pair_lut[i].id;
83 bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[i].addr);
84 bt_conn_get_dst_fake.return_val = &conn.le.dst;
85 func(&conn, data);
86 }
87 }
88
bt_conn_foreach_no_keys_in_use_custom_fake(enum bt_conn_type type,bt_conn_foreach_cb func,void * data)89 static void bt_conn_foreach_no_keys_in_use_custom_fake(enum bt_conn_type type,
90 bt_conn_foreach_cb func, void *data)
91 {
92 struct bt_conn conn;
93
94 /* This will make the effect as if key at slot 'x' is in use with a connection */
95 for (size_t i = 0; i < ARRAY_SIZE(testing_id_addr_pair_lut); i++) {
96 conn.state = BT_CONN_DISCONNECTED;
97 conn.id = testing_id_addr_pair_lut[i].id;
98 bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[i].addr);
99 bt_conn_get_dst_fake.return_val = &conn.le.dst;
100 func(&conn, data);
101 }
102 }
103
104 /* Setup test variables */
test_case_setup(void * f)105 static void test_case_setup(void *f)
106 {
107 Z_TEST_SKIP_IFNDEF(CONFIG_BT_KEYS_OVERWRITE_OLDEST);
108
109 clear_key_pool();
110
111 int rv = fill_key_pool_by_id_addr(testing_id_addr_pair_lut,
112 ARRAY_SIZE(testing_id_addr_pair_lut), returned_keys_refs);
113
114 zassert_true(rv == 0, "Failed to fill keys pool list, error code %d", -rv);
115 }
116
117 ZTEST_SUITE(bt_keys_get_addr_full_list_overwrite_oldest, NULL, NULL, test_case_setup, NULL, NULL);
118
119 /*
120 * Test adding extra (ID, Address) pair while the keys pool list is full while all keys are in
121 * use with connections so that no more (ID, Address) pairs can be added.
122 *
123 * Constraints:
124 * - Keys pool list is full
125 * - All Keys are used with a connection
126 * - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
127 *
128 * Expected behaviour:
129 * - NULL pointer is returned as there is no room
130 */
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest,test_full_list_all_keys_in_use)131 ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_all_keys_in_use)
132 {
133 struct bt_keys *returned_key;
134 uint8_t id = BT_ADDR_ID_3;
135 bt_addr_le_t *addr = BT_ADDR_LE_3;
136
137 bt_unpair_fake.custom_fake = bt_unpair_unreachable_custom_fake;
138 bt_conn_foreach_fake.custom_fake = bt_conn_foreach_all_keys_in_use_custom_fake;
139
140 returned_key = bt_keys_get_addr(id, addr);
141
142 zassert_true(returned_key == NULL, "bt_keys_get_addr() returned a non-NULL reference");
143 }
144
145 /*
146 * Test adding extra (ID, Address) pair while the keys pool list is full, but no keys are used with
147 * connections. New (ID, Address) pairs can be added by replacing the oldest pair.
148 *
149 * Constraints:
150 * - Keys pool list is full
151 * - All Keys are not used with a connection
152 * - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
153 *
154 * Expected behaviour:
155 * - A valid pointer in the keys pool is returned, matching the one previously assigned to the
156 * oldest key (index 0).
157 */
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest,test_full_list_no_keys_in_use)158 ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_no_keys_in_use)
159 {
160 struct bt_keys *returned_key;
161 uint8_t id = BT_ADDR_ID_3;
162 bt_addr_le_t *addr = BT_ADDR_LE_3;
163 uint32_t expected_oldest_params_ref_idx;
164
165 expected_oldest_params_ref_idx = 0;
166 oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
167 bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
168 bt_conn_foreach_fake.custom_fake = bt_conn_foreach_no_keys_in_use_custom_fake;
169
170 returned_key = bt_keys_get_addr(id, addr);
171
172 zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
173 zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
174 "bt_keys_get_addr() returned reference doesn't match expected one");
175 }
176
177 /*
178 * Test adding extra (ID, Address) pair while the keys pool list is full when the oldest key slot
179 * is in use with a connection but others keys aren't.
180 * New (ID, address) pair should replace the oldest one that's not in use.
181 *
182 * Constraints:
183 * - Keys pool list is full
184 * - Oldest key at slot 0 is used with a connection
185 * - Next oldest key (slot 1) isn't used with a connection
186 * - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
187 *
188 * Expected behaviour:
189 * - A valid pointer in the keys pool is returned, matching the one previously assigned to the
190 * oldest key (index 1).
191 */
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest,test_full_list_key_0_in_use_key_1_oldest)192 ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_key_0_in_use_key_1_oldest)
193 {
194 struct bt_keys *returned_key;
195 uint8_t id = BT_ADDR_ID_4;
196 bt_addr_le_t *addr = BT_ADDR_LE_4;
197 uint32_t expected_oldest_params_ref_idx;
198
199 expected_oldest_params_ref_idx = 1;
200 oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
201 bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
202 bt_conn_foreach_fake.custom_fake = bt_conn_foreach_key_slot_0_in_use_custom_fake;
203
204 returned_key = bt_keys_get_addr(id, addr);
205
206 zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
207 zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
208 "bt_keys_get_addr() returned reference doesn't match expected one");
209 }
210
211 /*
212 * Test adding extra (ID, Address) pair while the keys pool list is full when the oldest key slot
213 * is in use with a connection but others keys aren't.
214 * New (ID, address) pair should replace the oldest one that's not in use.
215 *
216 * Constraints:
217 * - Keys pool list is full
218 * - Key at slot 0 is used with a connection
219 * - oldest key (slot 2) isn't used with a connection
220 * - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
221 *
222 * Expected behaviour:
223 * - A valid pointer in the keys pool is returned, matching the one previously assigned to the
224 * oldest key (index 2).
225 */
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest,test_full_list_key_0_in_use_key_2_oldest)226 ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_key_0_in_use_key_2_oldest)
227 {
228 struct bt_keys *returned_key;
229 uint8_t id = BT_ADDR_ID_5;
230 bt_addr_le_t *addr = BT_ADDR_LE_5;
231 uint32_t expected_oldest_params_ref_idx;
232
233 #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
234 /* Normally first items inserted in the list are the oldest.
235 * For this particular test, we need to override that by setting
236 * the 'aging_counter'
237 */
238 returned_keys_refs[1]->aging_counter = bt_keys_get_aging_counter_val();
239 #endif
240
241 expected_oldest_params_ref_idx = 2;
242 oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
243 bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
244 bt_conn_foreach_fake.custom_fake = bt_conn_foreach_key_slot_0_in_use_custom_fake;
245
246 returned_key = bt_keys_get_addr(id, addr);
247
248 zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
249 zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
250 "bt_keys_get_addr() returned reference doesn't match expected one");
251 }
252