diff --git a/gateway/Kconfig b/gateway/Kconfig index 1a97212..56e9f19 100644 --- a/gateway/Kconfig +++ b/gateway/Kconfig @@ -1,9 +1,15 @@ # Copyright (c) 2025 Golioth, Inc. # SPDX-License-Identifier: Apache-2.0 +configdefault NET_SHELL + default n + configdefault MBEDTLS_USE_PSA_CRYPTO default n +configdefault MBEDTLS_HEAP_SIZE + default 16384 + configdefault BT_CTLR_DATA_LENGTH_MAX default 251 diff --git a/gateway/prj.conf b/gateway/prj.conf index 34e658f..824c974 100644 --- a/gateway/prj.conf +++ b/gateway/prj.conf @@ -51,3 +51,9 @@ CONFIG_PSA_WANT_ALG_SHA_384=y CONFIG_PSA_WANT_ECC_SECP_R1_256=y CONFIG_PSA_WANT_ECC_SECP_R1_384=y CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y + +# Bluetooth secure connections +CONFIG_BT_SMP=y +CONFIG_MBEDTLS_ECP_C=y +# This option is implied by BT_SMP and breaks secp384r1 support +CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED=n diff --git a/gateway/src/main.c b/gateway/src/main.c index 5b7dce6..3d38a18 100644 --- a/gateway/src/main.c +++ b/gateway/src/main.c @@ -160,6 +160,15 @@ static void bt_connected(struct bt_conn *conn, uint8_t err) LOG_INF("Connected: %s", addr); + err = bt_conn_set_security(conn, BT_SECURITY_L2); + if (err) + { + LOG_ERR("Failed to set security (%d).", err); + + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + return; + } + pouch_gateway_bt_start(conn); } @@ -177,9 +186,47 @@ static void bt_disconnected(struct bt_conn *conn, uint8_t reason) pouch_gateway_scan_start(); } +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + LOG_INF("BT security changed to level %u, err %s(%u)", level, bt_security_err_to_str(err), err); +} + BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = bt_connected, .disconnected = bt_disconnected, + .security_changed = security_changed, +}; + +static void auth_cancel(struct bt_conn *conn) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_INF("Pairing cancelled: %s", addr); +} + +static struct bt_conn_auth_cb auth_cb = { + .cancel = auth_cancel, +}; + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + LOG_INF("Pairing Complete"); +} + +static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) +{ + LOG_WRN("Pairing Failed (%d). Disconnecting.", reason); + + bt_conn_disconnect(conn, + (reason == BT_SECURITY_ERR_PAIR_NOT_ALLOWED) ? BT_HCI_ERR_PAIRING_NOT_ALLOWED + : BT_HCI_ERR_AUTH_FAIL); +} + +static struct bt_conn_auth_info_cb auth_info_cb = { + .pairing_complete = pairing_complete, + .pairing_failed = pairing_failed, }; void pouch_gateway_bt_finished(struct bt_conn *conn) @@ -205,6 +252,12 @@ int main(void) return err; } + if (IS_ENABLED(CONFIG_BT_SMP)) + { + bt_conn_auth_cb_register(&auth_cb); + bt_conn_auth_info_cb_register(&auth_info_cb); + } + LOG_INF("Bluetooth initialized"); pouch_gateway_scan_start(); diff --git a/samples/custom_connect/Kconfig b/samples/custom_connect/Kconfig index 1a97212..56e9f19 100644 --- a/samples/custom_connect/Kconfig +++ b/samples/custom_connect/Kconfig @@ -1,9 +1,15 @@ # Copyright (c) 2025 Golioth, Inc. # SPDX-License-Identifier: Apache-2.0 +configdefault NET_SHELL + default n + configdefault MBEDTLS_USE_PSA_CRYPTO default n +configdefault MBEDTLS_HEAP_SIZE + default 16384 + configdefault BT_CTLR_DATA_LENGTH_MAX default 251 diff --git a/samples/custom_connect/prj.conf b/samples/custom_connect/prj.conf index 34e658f..824c974 100644 --- a/samples/custom_connect/prj.conf +++ b/samples/custom_connect/prj.conf @@ -51,3 +51,9 @@ CONFIG_PSA_WANT_ALG_SHA_384=y CONFIG_PSA_WANT_ECC_SECP_R1_256=y CONFIG_PSA_WANT_ECC_SECP_R1_384=y CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y + +# Bluetooth secure connections +CONFIG_BT_SMP=y +CONFIG_MBEDTLS_ECP_C=y +# This option is implied by BT_SMP and breaks secp384r1 support +CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED=n diff --git a/samples/custom_connect/src/main.c b/samples/custom_connect/src/main.c index 6bcdaed..45e1bd0 100644 --- a/samples/custom_connect/src/main.c +++ b/samples/custom_connect/src/main.c @@ -132,6 +132,15 @@ static void bt_connected(struct bt_conn *conn, uint8_t err) LOG_INF("Connected: %s", addr); + err = bt_conn_set_security(conn, BT_SECURITY_L2); + if (err) + { + LOG_ERR("Failed to set security (%d).", err); + + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + return; + } + sync_data.conn = conn; sync_data.counter = 0; @@ -152,9 +161,47 @@ static void bt_disconnected(struct bt_conn *conn, uint8_t reason) custom_scan_start(); } +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + LOG_INF("BT security changed to level %u, err %s(%u)", level, bt_security_err_to_str(err), err); +} + BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = bt_connected, .disconnected = bt_disconnected, + .security_changed = security_changed, +}; + +static void auth_cancel(struct bt_conn *conn) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_INF("Pairing cancelled: %s", addr); +} + +static struct bt_conn_auth_cb auth_cb = { + .cancel = auth_cancel, +}; + +static void pairing_complete(struct bt_conn *conn, bool bonded) +{ + LOG_INF("Pairing Complete"); +} + +static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) +{ + LOG_WRN("Pairing Failed (%d). Disconnecting.", reason); + + bt_conn_disconnect(conn, + (reason == BT_SECURITY_ERR_PAIR_NOT_ALLOWED) ? BT_HCI_ERR_PAIRING_NOT_ALLOWED + : BT_HCI_ERR_AUTH_FAIL); +} + +static struct bt_conn_auth_info_cb auth_info_cb = { + .pairing_complete = pairing_complete, + .pairing_failed = pairing_failed, }; static void sync_start_handler(struct k_work *work) @@ -198,6 +245,12 @@ int main(void) return err; } + if (IS_ENABLED(CONFIG_BT_SMP)) + { + bt_conn_auth_cb_register(&auth_cb); + bt_conn_auth_info_cb_register(&auth_info_cb); + } + LOG_INF("Bluetooth initialized"); custom_scan_start();