Hi,
I am developing a BLE secure connection with the help of Dev Academy.
I found out that what I am implementing is Legacy Pairing, not LE Secure Connections.
This is my implementation and configuration.
//BLE_Security_NUS
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/conn.h>
#include <dk_buttons_and_leds.h>
#include <bluetooth/services/nus.h>
#include <zephyr/settings/settings.h>
LOG_MODULE_REGISTER(NUS_BLE_Security, LOG_LEVEL_INF);
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
#define RUN_STATUS_LED DK_LED1
#define CON_STATUS_LED DK_LED2
#define RUN_LED_BLINK_INTERVAL 1000
#define USER_BUTTON DK_BTN1_MSK
#define BOND_DELETE_BUTTON DK_BTN2_MSK
#define PAIRING_BUTTON DK_BTN3_MSK
/* STEP 3.2.1 - Define advertising parameter for no Accept List */
#define BT_LE_ADV_CONN_NO_ACCEPT_LIST \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, \
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL)
#define BT_LE_ADV_CONN_ACCEPT_LIST \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_FILTER_CONN | \
BT_LE_ADV_OPT_ONE_TIME, \
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL)
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static const struct bt_data sd[] = {
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};
/* STEP 3.3.1 - Define the callback to add addreses to the Accept List */
static void setup_accept_list_cb(const struct bt_bond_info *info, void *user_data)
{
int *bond_cnt = user_data;
if ((*bond_cnt) < 0) {
return;
}
int err = bt_le_filter_accept_list_add(&info->addr);
LOG_INF("Added following peer to accept list: %x %x\n", info->addr.a.val[0],
info->addr.a.val[1]);
if (err) {
LOG_INF("Cannot add peer to filter accept list (err: %d)\n", err);
(*bond_cnt) = -EIO;
} else {
(*bond_cnt)++;
}
}
/* STEP 3.3.2 - Define the function to loop through the bond list */
static int setup_accept_list(uint8_t local_id)
{
int err = bt_le_filter_accept_list_clear();
if (err) {
LOG_INF("Cannot clear accept list (err: %d)\n", err);
return err;
}
int bond_cnt = 0;
bt_foreach_bond(local_id, setup_accept_list_cb, &bond_cnt);
return bond_cnt;
}
/* STEP 3.4.1 - Define the function to advertise with the Accept List */
void advertise_with_acceptlist(struct k_work *work)
{
int err = 0;
int allowed_cnt = setup_accept_list(BT_ID_DEFAULT);
if (allowed_cnt < 0) {
LOG_INF("Acceptlist setup failed (err:%d)\n", allowed_cnt);
} else {
if (allowed_cnt == 0) {
LOG_INF("Disconnected reason = %d \n", allowed_cnt);
err = bt_le_adv_start(BT_LE_ADV_CONN_ACCEPT_LIST, ad, ARRAY_SIZE(ad), sd,
ARRAY_SIZE(sd));
} else {
LOG_INF("Acceptlist setup number = %d \n", allowed_cnt);
err = bt_le_adv_start(BT_LE_ADV_CONN_ACCEPT_LIST, ad, ARRAY_SIZE(ad), sd,
ARRAY_SIZE(sd));
}
if (err) {
LOG_INF("Advertising failed to start (err %d)\n", err);
return;
}
LOG_INF("Advertising successfully started\n");
}
}
K_WORK_DEFINE(advertise_acceptlist_work, advertise_with_acceptlist);
static void on_connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
LOG_INF("Connection failed (err %u)\n", err);
return;
}
LOG_INF("Connected\n");
dk_set_led_on(CON_STATUS_LED);
}
static void on_disconnected(struct bt_conn *conn, uint8_t reason)
{
LOG_INF("Disconnected (reason %u)\n", reason);
dk_set_led_off(CON_STATUS_LED);
/* STEP 3.5 - Start advertising with Accept List */
k_work_submit(&advertise_acceptlist_work);
}
static void on_security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (!err) {
LOG_INF("Security changed: %s level %u\n", addr, level);
} else {
LOG_INF("Security failed: %s level %u err %d\n", addr, level, err);
}
}
struct bt_conn_cb connection_callbacks = {
.connected = on_connected,
.disconnected = on_disconnected,
.security_changed = on_security_changed,
};
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *data, uint16_t len)
{
char addr[BT_ADDR_LE_STR_LEN] = {0};
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Received data from: %s", addr);
char log_data[len + 1];
memcpy(log_data, data, len);
log_data[len] = '\0'; // Null-terminate the string
LOG_INF("Received data: %s", log_data);
LOG_INF("Received data length: %d", len);
while (len > 0 && (data[len - 1] == '\r' || data[len - 1] == '\n')) {
len--;
}
if (len == 5 && memcmp(data, "apple", 5) == 0) {
LOG_INF("Match found: apple");
const char *response = "OK";
int err = bt_nus_send(conn, response, strlen(response));
if (err) {
LOG_ERR("Failed to send OK response: %d", err);
} else {
LOG_INF("Sent OK response");
}
} else {
LOG_INF("No match found");
const char *response = "NO";
int err = bt_nus_send(conn, response, strlen(response));
if (err) {
LOG_ERR("Failed to send NO response: %d", err);
} else {
LOG_INF("Sent NO response");
}
}
}
static struct bt_nus_cb nus_cb = {
.received = bt_receive_cb,
};
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Passkey for %s: %06u\n", addr, passkey);
}
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\n", addr);
}
static struct bt_conn_auth_cb conn_auth_callbacks = {
.passkey_display = auth_passkey_display,
.cancel = auth_cancel,
};
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
/* STEP 2.2 - Add extra button handling to remove bond information */
if (has_changed & BOND_DELETE_BUTTON) {
uint32_t bond_delete_button_state = button_state & BOND_DELETE_BUTTON;
if (bond_delete_button_state == 0) {
int err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
if (err) {
LOG_INF("Cannot delete bond (err: %d)\n", err);
} else {
LOG_INF("Bond deleted succesfully");
}
}
}
/* STEP 4.2.2 Add extra button handling to advertise without using Accept List */
if (has_changed & PAIRING_BUTTON) {
uint32_t pairing_button_state = button_state & PAIRING_BUTTON;
if (pairing_button_state == 0) {
int err_code = bt_le_adv_stop();
// int err_code = bt_le_adv_stop();
if (err_code) {
LOG_INF("Cannot stop advertising err= %d \n", err_code);
return;
}
err_code = bt_le_filter_accept_list_clear();
if (err_code) {
LOG_INF("Cannot clear accept list (err: %d)\n", err_code);
} else {
LOG_INF("Accept list cleared succesfully");
}
err_code = bt_le_adv_start(BT_LE_ADV_CONN_NO_ACCEPT_LIST, ad,
ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err_code) {
LOG_INF("Cannot start open advertising (err: %d)\n", err_code);
} else {
LOG_INF("Advertising in pairing mode started");
}
}
}
}
static int init_button(void)
{
int err;
err = dk_buttons_init(button_changed);
if (err) {
LOG_INF("Cannot init buttons (err: %d)\n", err);
}
return err;
}
int main(void)
{
int blink_status = 0;
int err;
LOG_INF("Starting Lesson 5 - Exercise 2 \n");
err = dk_leds_init();
if (err) {
LOG_INF("LEDs init failed (err %d)\n", err);
return -1;
}
err = init_button();
if (err) {
LOG_INF("Button init failed (err %d)\n", err);
return -1;
}
err = bt_conn_auth_cb_register(&conn_auth_callbacks);
if (err) {
LOG_INF("Failed to register authorization callbacks.\n");
return -1;
}
bt_conn_cb_register(&connection_callbacks);
err = bt_enable(NULL);
if (err) {
LOG_INF("Bluetooth init failed (err %d)\n", err);
return -1;
}
LOG_INF("Bluetooth initialized\n");
/* STEP 1.3 - Add setting load function */
settings_load();
err = bt_nus_init(&nus_cb);
if (err) {
LOG_ERR("Failed to initialize NUS service (err: %d)", err);
return 0;
}
bt_le_adv_start(BT_LE_ADV_CONN_ACCEPT_LIST, ad, ARRAY_SIZE(ad), sd,
ARRAY_SIZE(sd));
for (;;) {
dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
}
}
/*
#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_GPIO=y
# Make sure printk is printing to the UART console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Nordic_UART_Service"
CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_PAIRED=1
# Enable the NUS service
CONFIG_BT_NUS=y
# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
# Enable DK LED and Buttons library
CONFIG_DK_LIBRARY=y
# This example requires more stack
# CONFIG_MAIN_STACK_SIZE=1152
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
# Config logger
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PRINTK=y
CONFIG_ASSERT=y
# Enable Security Management Protocol
CONFIG_BT_SMP=y
CONFIG_BT_FILTER_ACCEPT_LIST=y
CONFIG_BT_PRIVACY=y
CONFIG_MAIN_STACK_SIZE=2048
*/To achieve LE Secure Connections, what changes do I need to make so that it works as LE Secure Connections?
The device that I am working on need's more security!!