Skip to content

Commit 1deb009

Browse files
alstrzebonskinordicjm
authored andcommitted
bluetooth: fast_pair: Add bond management
Implements Fast Pair bond management. Associates bonds with Account Keys and removes bonds when associated Account Keys are removed. Adds the bond manager module that handles Bluetooth operations needed by Fast Pair storage module to handle bond management. Jira: NCSDK-18829 Signed-off-by: Aleksander Strzebonski <[email protected]>
1 parent 3759c89 commit 1deb009

File tree

14 files changed

+1148
-81
lines changed

14 files changed

+1148
-81
lines changed

subsys/bluetooth/services/fast_pair/CMakeLists.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@ zephyr_library_include_directories(include/common)
1212
# during Key-based Pairing write.
1313
zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth)
1414

15-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_ADVERTISING fp_advertising.c)
16-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_AUTH fp_auth.c)
17-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_GATT_SERVICE fp_gatt_service.c)
18-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_KEYS fp_keys.c)
19-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_REGISTRATION_DATA fp_registration_data.c)
20-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_BATTERY fp_battery.c)
21-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_STORAGE_INTEGRATION fp_storage_integration.c)
22-
23-
zephyr_linker_sources_ifdef(CONFIG_BT_FAST_PAIR_ACTIVATION SECTIONS fp_activation.ld)
24-
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_ACTIVATION fp_activation.c)
15+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_ADVERTISING fp_advertising.c)
16+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_AUTH fp_auth.c)
17+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_GATT_SERVICE fp_gatt_service.c)
18+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_KEYS fp_keys.c)
19+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_REGISTRATION_DATA fp_registration_data.c)
20+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_BATTERY fp_battery.c)
21+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_STORAGE_INTEGRATION fp_storage_integration.c)
22+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_BOND_MANAGER fp_bond_manager.c)
23+
24+
zephyr_linker_sources_ifdef(CONFIG_BT_FAST_PAIR_ACTIVATION SECTIONS fp_activation.ld)
25+
zephyr_library_sources_ifdef(CONFIG_BT_FAST_PAIR_ACTIVATION fp_activation.c)
2526

2627
if(CONFIG_BT_FAST_PAIR_CRYPTO)
2728
add_subdirectory(fp_crypto)

subsys/bluetooth/services/fast_pair/Kconfig.fast_pair

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,12 @@ if BT_FAST_PAIR_REGISTRATION_DATA
140140
config BT_FAST_PAIR_REGISTRATION_DATA_INIT_PRIORITY
141141
int
142142
range 0 9
143-
default 3
143+
default 0
144144
help
145145
Fast Pair registration data module initialization priority.
146146
Used when registering initialization function to Fast Pair activation module.
147+
This module should be initialized before all other Fast Pair modules to avoid using
148+
Fast Pair subsystem when the Fast Pair provisioning data is not configured properly.
147149

148150
endif # BT_FAST_PAIR_REGISTRATION_DATA
149151

@@ -170,6 +172,22 @@ config BT_FAST_PAIR_STORAGE_INTEGRATION_INIT_PRIORITY
170172

171173
endif # BT_FAST_PAIR_STORAGE_INTEGRATION
172174

175+
config BT_FAST_PAIR_BOND_MANAGER
176+
bool "Fast Pair bond management functionality [EXPERIMENTAL]"
177+
select EXPERIMENTAL
178+
select BT_FAST_PAIR_STORAGE_AK_BOND
179+
help
180+
If this option is enabled, the Fast Pair subsystem tracks the Bluetooth bonds created
181+
through the Fast Pair Procedure and unpairs them if the Fast Pair Procedure is incomplete
182+
or the Account Key associated with the bonds is removed. It also unpairs the Fast Pair
183+
Bluetooth bonds on Fast Pair factory reset. Keep in mind that when the Fast Pair subsystem
184+
is disabled, the Bluetooth bonds are not tracked. Do not perform operations on the Fast
185+
Pair Bluetooth bonds apart from the Fast Pair factory reset when the Fast Pair subsystem
186+
is disabled. When this option is enabled, non-volatile storage is used to store the bond
187+
information. You can enable this option during DFU, but you cannot disable it during DFU
188+
if you used it earlier unless you erase whole Fast Pair non-volatile storage. Otherwise,
189+
the Fast Pair enable operation will fail.
190+
173191
module = BT_FAST_PAIR
174192
module-str = Fast Pair Service
175193
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"

subsys/bluetooth/services/fast_pair/fp_auth.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ LOG_MODULE_DECLARE(fast_pair, CONFIG_BT_FAST_PAIR_LOG_LEVEL);
1515
#include "fp_activation.h"
1616
#include "fp_auth.h"
1717
#include "fp_keys.h"
18+
#include "fp_storage_ak_bond.h"
1819

1920
#define EMPTY_PASSKEY 0xffffffff
2021
#define USED_PASSKEY 0xfffffffe
@@ -68,15 +69,25 @@ static void clear_conn_context(const struct bt_conn *conn)
6869

6970
static int send_auth_confirm(struct bt_conn *conn)
7071
{
71-
int err = bt_conn_auth_passkey_confirm(conn);
72+
int err;
73+
74+
if (IS_ENABLED(CONFIG_BT_FAST_PAIR_BOND_MANAGER)) {
75+
/* Saving potential bond. */
76+
err = fp_keys_bond_save(conn);
77+
if (err) {
78+
LOG_ERR("Failed to save potential bond %d", err);
79+
return err;
80+
}
81+
}
7282

83+
err = bt_conn_auth_passkey_confirm(conn);
7384
if (err) {
7485
LOG_ERR("Failed to confirm passkey (err: %d)", err);
75-
} else {
76-
LOG_DBG("Confirmed passkey");
86+
return err;
7787
}
88+
LOG_DBG("Confirmed passkey");
7889

79-
return err;
90+
return 0;
8091
}
8192

8293
static int send_auth_cancel(struct bt_conn *conn)
@@ -212,6 +223,18 @@ static void pairing_complete(struct bt_conn *conn, bool bonded)
212223
}
213224

214225
if (bt_conn_get_security(conn) >= BT_SECURITY_L4) {
226+
if (IS_ENABLED(CONFIG_BT_FAST_PAIR_BOND_MANAGER) && bonded) {
227+
struct bt_conn_info conn_info;
228+
int err;
229+
230+
err = bt_conn_get_info(conn, &conn_info);
231+
if (err) {
232+
LOG_ERR("Failed to get local conn info (err %d)", err);
233+
return;
234+
}
235+
236+
fp_storage_ak_bond_conn_confirm(conn, conn_info.le.dst);
237+
}
215238
fp_keys_bt_auth_progress(conn, true);
216239
} else {
217240
LOG_ERR("Invalid conn security level after pairing: %p", (void *)conn);
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <errno.h>
8+
#include <zephyr/bluetooth/conn.h>
9+
10+
#include <bluetooth/services/fast_pair/fast_pair.h>
11+
12+
#include <zephyr/logging/log.h>
13+
LOG_MODULE_DECLARE(fast_pair, CONFIG_BT_FAST_PAIR_LOG_LEVEL);
14+
15+
#include "fp_activation.h"
16+
#include "fp_storage_ak_bond.h"
17+
18+
struct bond_find_ctx {
19+
bool bond_found;
20+
const bt_addr_le_t *bond_addr;
21+
};
22+
23+
static bool is_enabled;
24+
25+
static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
26+
const bt_addr_le_t *identity)
27+
{
28+
if (!bt_fast_pair_is_ready()) {
29+
return;
30+
}
31+
32+
LOG_DBG("Identity resolved");
33+
34+
fp_storage_ak_bond_conn_addr_update(conn, identity);
35+
}
36+
37+
static void disconnected(struct bt_conn *conn, uint8_t reason)
38+
{
39+
if (!bt_fast_pair_is_ready()) {
40+
return;
41+
}
42+
43+
fp_storage_ak_bond_conn_finalize(conn);
44+
}
45+
46+
BT_CONN_CB_DEFINE(conn_callbacks) = {
47+
.disconnected = disconnected,
48+
.identity_resolved = identity_resolved,
49+
};
50+
51+
static void bond_deleted(uint8_t id, const bt_addr_le_t *peer)
52+
{
53+
if (!bt_fast_pair_is_ready()) {
54+
return;
55+
}
56+
57+
fp_storage_ak_bond_delete(peer);
58+
}
59+
60+
static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
61+
.bond_deleted = bond_deleted,
62+
};
63+
64+
static void bond_address_cmp(const struct bt_bond_info *info, void *user_data)
65+
{
66+
struct bond_find_ctx *ctx = user_data;
67+
68+
if (bt_addr_le_eq(ctx->bond_addr, &info->addr)) {
69+
__ASSERT_NO_MSG(!ctx->bond_found);
70+
ctx->bond_found = true;
71+
}
72+
}
73+
74+
static int bond_identity_find(uint8_t *identity, const bt_addr_le_t *addr)
75+
{
76+
struct bond_find_ctx ctx = {
77+
.bond_found = false,
78+
.bond_addr = addr,
79+
};
80+
81+
for (uint8_t id = 0; id < CONFIG_BT_ID_MAX; id++) {
82+
bt_foreach_bond(id, bond_address_cmp, &ctx);
83+
if (ctx.bond_found) {
84+
if (identity) {
85+
*identity = id;
86+
}
87+
}
88+
}
89+
90+
return ctx.bond_found ? 0 : -ESRCH;
91+
}
92+
93+
static int bond_remove(const bt_addr_le_t *addr)
94+
{
95+
uint8_t identity;
96+
int err;
97+
98+
err = bond_identity_find(&identity, addr);
99+
if (err) {
100+
return err;
101+
}
102+
103+
return bt_unpair(identity, addr);
104+
}
105+
106+
static bool is_addr_bonded(const bt_addr_le_t *addr)
107+
{
108+
return !bond_identity_find(NULL, addr);
109+
}
110+
111+
static const struct fp_storage_ak_bond_bt_request_cb bt_request_cb = {
112+
.bond_remove = bond_remove,
113+
.is_addr_bonded = is_addr_bonded,
114+
};
115+
116+
static int bt_request_cb_register(void)
117+
{
118+
fp_storage_ak_bond_bt_request_cb_register(&bt_request_cb);
119+
return 0;
120+
}
121+
122+
static int bond_manager_init(void)
123+
{
124+
if (is_enabled) {
125+
LOG_WRN("fp_bond_manager module already initialized");
126+
return 0;
127+
}
128+
129+
int err;
130+
131+
err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
132+
if (err) {
133+
return err;
134+
}
135+
136+
is_enabled = true;
137+
138+
return 0;
139+
}
140+
141+
static int bond_manager_uninit(void)
142+
{
143+
if (!is_enabled) {
144+
LOG_WRN("fp_bond_manager module already uninitialized");
145+
return 0;
146+
}
147+
148+
int err;
149+
150+
is_enabled = false;
151+
152+
err = bt_conn_auth_info_cb_unregister(&conn_auth_info_callbacks);
153+
if (err) {
154+
return err;
155+
}
156+
157+
return 0;
158+
}
159+
160+
/* Register fp_storage_ak_bond_bt_request_cb callback structure to be able to remove Bluetooth
161+
* bonds during Fast Pair storage factory reset even if the Fast Pair is not enabled.
162+
*/
163+
SYS_INIT(bt_request_cb_register, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
164+
165+
FP_ACTIVATION_MODULE_REGISTER(fp_bond_manager, FP_ACTIVATION_INIT_PRIORITY_DEFAULT,
166+
bond_manager_init, bond_manager_uninit);

subsys/bluetooth/services/fast_pair/fp_keys.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ LOG_MODULE_DECLARE(fast_pair, CONFIG_BT_FAST_PAIR_LOG_LEVEL);
1919
#include "fp_crypto.h"
2020
#include "fp_common.h"
2121
#include "fp_storage_ak.h"
22+
#include "fp_storage_ak_bond.h"
2223
#include "fp_storage_pn.h"
2324

2425
#define EMPTY_AES_KEY_BYTE 0xff
@@ -370,7 +371,7 @@ int fp_keys_store_account_key(const struct bt_conn *conn, const struct fp_accoun
370371
LOG_WRN("Received invalid Account Key");
371372
return -EINVAL;
372373
}
373-
err = fp_storage_ak_save(account_key);
374+
err = fp_storage_ak_save(account_key, conn);
374375
if (!err) {
375376
LOG_DBG("Account Key stored");
376377
} else {
@@ -533,5 +534,40 @@ static int fp_keys_uninit(void)
533534
return 0;
534535
}
535536

537+
int fp_keys_bond_save(const struct bt_conn *conn)
538+
{
539+
if (!IS_ENABLED(CONFIG_BT_FAST_PAIR_BOND_MANAGER)) {
540+
__ASSERT_NO_MSG(false);
541+
return -ENOTSUP;
542+
}
543+
__ASSERT_NO_MSG(bt_fast_pair_is_ready());
544+
545+
struct fp_procedure *proc = &fp_procedures[bt_conn_index(conn)];
546+
struct bt_conn_info conn_info;
547+
int err;
548+
549+
err = bt_conn_get_info(conn, &conn_info);
550+
if (err) {
551+
LOG_ERR("Failed to get local conn info (err %d)", err);
552+
return err;
553+
}
554+
555+
if (proc->state == FP_STATE_USE_TEMP_KEY) {
556+
/* Initial pairing - the Account Key is not written yet. */
557+
err = fp_storage_ak_bond_conn_create(conn, conn_info.le.dst, NULL);
558+
} else if (proc->state == FP_STATE_USE_TEMP_ACCOUNT_KEY) {
559+
/* Subsequent pairing - the Account Key is already known. */
560+
struct fp_account_key account_key;
561+
562+
memcpy(account_key.key, proc->aes_key, sizeof(account_key.key));
563+
err = fp_storage_ak_bond_conn_create(conn, conn_info.le.dst, &account_key);
564+
} else {
565+
__ASSERT_NO_MSG(false);
566+
err = -EACCES;
567+
}
568+
569+
return err;
570+
}
571+
536572
FP_ACTIVATION_MODULE_REGISTER(fp_keys, FP_ACTIVATION_INIT_PRIORITY_DEFAULT, fp_keys_init,
537573
fp_keys_uninit);

subsys/bluetooth/services/fast_pair/fp_storage/Kconfig.fp_storage

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ config BT_FAST_PAIR_STORAGE
88
bool
99
default y
1010
select SETTINGS
11+
select BT_FAST_PAIR_STORAGE_AK
1112
help
1213
Add Fast Pair storage source files.
1314

@@ -32,6 +33,22 @@ config BT_FAST_PAIR_STORAGE_OWNER_ACCOUNT_KEY
3233
help
3334
Enable support for the Owner Account Key in the Storage module.
3435

36+
config BT_FAST_PAIR_STORAGE_AK_BOND
37+
bool
38+
help
39+
Enable support for the bond management in the Storage module. If this options is enabled,
40+
the Storage module tracks the Bluetooth bonds created through the Fast Pair Procedure and
41+
requests to unpair them if the Fast Pair Procedure is incomplete or the Account Key
42+
associated with the bonds is removed. It also requests to unpair the Fast Pair Bluetooth
43+
bonds on Fast Pair factory reset.
44+
45+
config BT_FAST_PAIR_STORAGE_AK
46+
bool
47+
depends on BT_FAST_PAIR_STORAGE_AK_BACKEND_STANDARD || \
48+
BT_FAST_PAIR_STORAGE_AK_BACKEND_MINIMAL
49+
help
50+
Enable support for the Account Key in the Storage module.
51+
3552
choice BT_FAST_PAIR_STORAGE_AK_BACKEND
3653
prompt "Account Key storage backend selection"
3754
help
@@ -48,6 +65,7 @@ config BT_FAST_PAIR_STORAGE_AK_BACKEND_STANDARD
4865
config BT_FAST_PAIR_STORAGE_AK_BACKEND_MINIMAL
4966
bool "Account Key storage minimal backend"
5067
depends on BT_FAST_PAIR_STORAGE_OWNER_ACCOUNT_KEY
68+
depends on !BT_FAST_PAIR_STORAGE_AK_BOND
5169
help
5270
Select Account Key storage minimal backend. It allows for storing only one Account Key,
5371
that is assumed to be an Owner Account Key.

0 commit comments

Comments
 (0)