Skip to content

Commit c589d12

Browse files
committed
gateway: add authentication support
Integrate bonding control into the gateway application with button-triggered pairing and passkey confirmation support. Enable 30 second window for bonding after first button press. Confirm passkey using second button press, during that window. Signed-off-by: Marcin Niestroj <[email protected]>
1 parent 355b6fb commit c589d12

File tree

7 files changed

+322
-46
lines changed

7 files changed

+322
-46
lines changed

gateway/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ configdefault MBEDTLS_HEAP_SIZE
1313
configdefault BT_CTLR_DATA_LENGTH_MAX
1414
default 251
1515

16+
# This option is used only for automated tests
17+
config SAMPLE_POUCH_GATEWAY_BT_AUTO_BOND
18+
bool
19+
default y if BOARD_NRF52_BSIM_NATIVE
20+
21+
# This option is used only for automated tests
22+
config SAMPLE_POUCH_GATEWAY_BT_AUTO_CONFIRM
23+
bool
24+
default y if BOARD_NRF52_BSIM_NATIVE
25+
1626
source "${ZEPHYR_GOLIOTH_FIRMWARE_SDK_MODULE_DIR}/examples/zephyr/common/Kconfig.defconfig"
1727

1828
source "Kconfig.zephyr"

gateway/sample.yaml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
sample:
22
name: Pouch Gateway
3+
common:
4+
tags: bluetooth
5+
harness: pytest
6+
harness_config:
7+
pytest_dut_scope: module
8+
sysbuild: true
9+
platform_allow:
10+
- nrf52_bsim
11+
integration_platforms:
12+
- nrf52_bsim
13+
timeout: 120
314
tests:
4-
pouch-gateway.gateway:
5-
tags: bluetooth
6-
harness: pytest
7-
harness_config:
8-
pytest_dut_scope: module
9-
sysbuild: true
10-
platform_allow:
11-
- nrf52_bsim
12-
integration_platforms:
13-
- nrf52_bsim
15+
pouch-gateway.gateway.lesc:
1416
extra_args:
1517
- SB_CONFIG_PERIPHERAL_MOUNT_CREDS=y
1618
- peripheral_ble_gatt_example_0_CONFIG_PICOLIBC=y
1719
- peripheral_ble_gatt_example_0_CONFIG_FILE_SYSTEM_NSIM_MOUNT=y
1820
- peripheral_ble_gatt_example_0_CONFIG_EXAMPLE_SYNC_PERIOD_S=2
19-
timeout: 120
21+
pouch-gateway.gateway.auth:
22+
extra_args:
23+
- SB_CONFIG_PERIPHERAL_MOUNT_CREDS=y
24+
- peripheral_ble_gatt_example_0_CONFIG_PICOLIBC=y
25+
- peripheral_ble_gatt_example_0_CONFIG_FILE_SYSTEM_NSIM_MOUNT=y
26+
- peripheral_ble_gatt_example_0_CONFIG_EXAMPLE_SYNC_PERIOD_S=2
27+
- gateway_CONFIG_POUCH_GATEWAY_GATT_SCAN_FILTER_BONDED=y

gateway/src/main.c

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
#include <zephyr/bluetooth/hci.h>
1010
#include <zephyr/net/net_if.h>
1111
#include <zephyr/net/dhcpv4.h>
12+
#include <zephyr/drivers/gpio.h>
1213

1314
#include <golioth/client.h>
1415
#include <golioth/gateway.h>
1516
#include <samples/common/sample_credentials.h>
1617

1718
#include <pouch/transport/gatt/common/types.h>
1819

20+
#include <pouch_gateway/bt/bond.h>
1921
#include <pouch_gateway/bt/connect.h>
2022
#include <pouch_gateway/bt/scan.h>
2123
#include <pouch_gateway/cert.h>
@@ -29,6 +31,31 @@ LOG_MODULE_REGISTER(main);
2931

3032
struct golioth_client *client;
3133

34+
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(DT_ALIAS(sw0), gpios, {});
35+
static struct gpio_callback button_cb_data;
36+
static struct bt_conn *default_conn;
37+
38+
static const k_timeout_t bonding_timeout = K_SECONDS(30);
39+
static const bt_security_t bt_security =
40+
IS_ENABLED(CONFIG_POUCH_GATEWAY_GATT_SCAN_FILTER_BONDED) ? BT_SECURITY_L4 : BT_SECURITY_L2;
41+
42+
static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
43+
{
44+
if (default_conn)
45+
{
46+
LOG_INF("Confirming passkey");
47+
bt_conn_auth_passkey_confirm(default_conn);
48+
}
49+
else if (pouch_gateway_bonding_is_enabled())
50+
{
51+
LOG_WRN("Bonding already enabled");
52+
}
53+
else
54+
{
55+
pouch_gateway_bonding_enable(bonding_timeout);
56+
}
57+
}
58+
3259
#ifdef CONFIG_POUCH_GATEWAY_CLOUD
3360

3461
static K_SEM_DEFINE(connected, 0, 1);
@@ -159,8 +186,9 @@ static void bt_connected(struct bt_conn *conn, uint8_t err)
159186
}
160187

161188
LOG_INF("Connected: %s", addr);
189+
default_conn = conn;
162190

163-
err = bt_conn_set_security(conn, BT_SECURITY_L2);
191+
err = bt_conn_set_security(conn, bt_security);
164192
if (err)
165193
{
166194
LOG_ERR("Failed to set security (%d).", err);
@@ -174,6 +202,8 @@ static void bt_disconnected(struct bt_conn *conn, uint8_t reason)
174202
{
175203
char addr[BT_ADDR_LE_STR_LEN];
176204

205+
default_conn = NULL;
206+
177207
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
178208
LOG_INF("Disconnected: %s, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));
179209

@@ -222,8 +252,43 @@ static void auth_cancel(struct bt_conn *conn)
222252
LOG_INF("Pairing cancelled: %s", addr);
223253
}
224254

255+
static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
256+
{
257+
char addr[BT_ADDR_LE_STR_LEN];
258+
char passkey_str[7];
259+
260+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
261+
262+
snprintk(passkey_str, 7, "%06u", passkey);
263+
264+
LOG_INF("Confirm passkey for %s: %s", addr, passkey_str);
265+
266+
if (IS_ENABLED(CONFIG_SAMPLE_POUCH_GATEWAY_BT_AUTO_CONFIRM))
267+
{
268+
LOG_INF("Confirming passkey");
269+
bt_conn_auth_passkey_confirm(conn);
270+
}
271+
}
272+
273+
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
274+
{
275+
char addr[BT_ADDR_LE_STR_LEN];
276+
char passkey_str[7];
277+
278+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
279+
280+
snprintk(passkey_str, 7, "%06u", passkey);
281+
282+
LOG_INF("Passkey for %s: %s", addr, passkey_str);
283+
}
284+
225285
static struct bt_conn_auth_cb auth_cb = {
226286
.cancel = auth_cancel,
287+
288+
.passkey_confirm =
289+
IS_ENABLED(CONFIG_POUCH_GATEWAY_GATT_SCAN_FILTER_BONDED) ? auth_passkey_confirm : NULL,
290+
.passkey_display =
291+
IS_ENABLED(CONFIG_POUCH_GATEWAY_GATT_SCAN_FILTER_BONDED) ? auth_passkey_display : NULL,
227292
};
228293

229294
static void pairing_complete(struct bt_conn *conn, bool bonded)
@@ -252,16 +317,42 @@ void pouch_gateway_bt_finished(struct bt_conn *conn)
252317

253318
int main(void)
254319
{
320+
int err;
321+
255322
LOG_INF("Gateway Version: " STRINGIFY(GIT_DESCRIBE));
256323
LOG_INF("Pouch BLE Transport Protocol Version: %d", POUCH_GATT_VERSION);
257324

325+
if (DT_HAS_ALIAS(sw0))
326+
{
327+
LOG_INF("Set up button at %s pin %d", button.port->name, button.pin);
328+
329+
err = gpio_pin_configure_dt(&button, GPIO_INPUT);
330+
if (err < 0)
331+
{
332+
LOG_ERR("Could not initialize Button");
333+
}
334+
335+
err = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
336+
if (err)
337+
{
338+
LOG_ERR("Error %d: failed to configure interrupt on %s pin %d",
339+
err,
340+
button.port->name,
341+
button.pin);
342+
return 0;
343+
}
344+
345+
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
346+
gpio_add_callback(button.port, &button_cb_data);
347+
}
348+
258349
connect_to_cloud();
259350

260351
pouch_gateway_cert_module_on_connected(client);
261352
pouch_gateway_uplink_module_init(client);
262353
pouch_gateway_downlink_module_init(client);
263354

264-
int err = bt_enable(NULL);
355+
err = bt_enable(NULL);
265356
if (err)
266357
{
267358
LOG_ERR("Bluetooth init failed (err %d)", err);
@@ -276,6 +367,11 @@ int main(void)
276367

277368
LOG_INF("Bluetooth initialized");
278369

370+
if (IS_ENABLED(CONFIG_SAMPLE_POUCH_GATEWAY_BT_AUTO_BOND))
371+
{
372+
pouch_gateway_bonding_enable(K_FOREVER);
373+
}
374+
279375
pouch_gateway_scan_start();
280376

281377
#ifdef CONFIG_POUCH_GATEWAY_CLOUD

samples/custom_connect/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ configdefault MBEDTLS_HEAP_SIZE
1313
configdefault BT_CTLR_DATA_LENGTH_MAX
1414
default 251
1515

16+
# This option is used only for automated tests
17+
config SAMPLE_POUCH_GATEWAY_BT_AUTO_BOND
18+
bool
19+
default y if BOARD_NRF52_BSIM_NATIVE
20+
21+
# This option is used only for automated tests
22+
config SAMPLE_POUCH_GATEWAY_BT_AUTO_CONFIRM
23+
bool
24+
default y if BOARD_NRF52_BSIM_NATIVE
25+
1626
source "${ZEPHYR_GOLIOTH_FIRMWARE_SDK_MODULE_DIR}/examples/zephyr/common/Kconfig.defconfig"
1727

1828
source "Kconfig.zephyr"

samples/custom_connect/sample.yaml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
sample:
22
name: Pouch Gateway with custom connect
3+
common:
4+
tags: bluetooth
5+
harness: pytest
6+
harness_config:
7+
pytest_dut_scope: module
8+
sysbuild: true
9+
platform_allow:
10+
- nrf52_bsim
11+
integration_platforms:
12+
- nrf52_bsim
13+
timeout: 120
314
tests:
4-
pouch-gateway.sample.custom_connect:
5-
tags: bluetooth
6-
harness: pytest
7-
harness_config:
8-
pytest_dut_scope: module
9-
sysbuild: true
10-
platform_allow:
11-
- nrf52_bsim
12-
integration_platforms:
13-
- nrf52_bsim
15+
pouch-gateway.sample.custom_connect.lesc:
1416
extra_args:
1517
- SB_CONFIG_PERIPHERAL_MOUNT_CREDS=y
1618
- peripheral_ble_gatt_example_0_CONFIG_PICOLIBC=y
1719
- peripheral_ble_gatt_example_0_CONFIG_FILE_SYSTEM_NSIM_MOUNT=y
1820
- peripheral_ble_gatt_example_0_CONFIG_EXAMPLE_SYNC_PERIOD_S=2
19-
timeout: 120
21+
pouch-gateway.sample.custom_connect.auth:
22+
extra_args:
23+
- SB_CONFIG_PERIPHERAL_MOUNT_CREDS=y
24+
- peripheral_ble_gatt_example_0_CONFIG_PICOLIBC=y
25+
- peripheral_ble_gatt_example_0_CONFIG_FILE_SYSTEM_NSIM_MOUNT=y
26+
- peripheral_ble_gatt_example_0_CONFIG_EXAMPLE_SYNC_PERIOD_S=2
27+
- custom_connect_CONFIG_POUCH_GATEWAY_GATT_SCAN_FILTER_BONDED=y

0 commit comments

Comments
 (0)