mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-11 11:13:11 +00:00
This commit introduces a new Kconfig symbol MCUMGR_SMP_BT_AUTHEN. When selected it configures the Bluetooth mcumgr transport to require an authenticated connection. If the Bluetooth mcumgr transport is selected then this new symbol is selected by default. Bluetooth SMP is also selected to ensure Zephyr is configured with Bluetooth security features enabled to provide Bluetooth authentication APIs to the user's app. Users can choose to disable this level of security for the Bluetooth mcumgr transport if they do not require it. Fixes #16482 Signed-off-by: Nick Ward <nix.ward@gmail.com>
204 lines
4.3 KiB
C
204 lines
4.3 KiB
C
/*
|
|
* Copyright Runtime.io 2018. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/** @file
|
|
* @brief Bluetooth transport for the mcumgr SMP protocol.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
|
|
#include <zephyr.h>
|
|
#include <init.h>
|
|
#include <bluetooth/bluetooth.h>
|
|
#include <bluetooth/uuid.h>
|
|
#include <bluetooth/gatt.h>
|
|
|
|
#include <mgmt/smp_bt.h>
|
|
#include <mgmt/buf.h>
|
|
|
|
#include <mgmt/smp.h>
|
|
|
|
struct device;
|
|
|
|
struct smp_bt_user_data {
|
|
struct bt_conn *conn;
|
|
};
|
|
|
|
static struct zephyr_smp_transport smp_bt_transport;
|
|
|
|
/* SMP service.
|
|
* {8D53DC1D-1DB7-4CD3-868B-8A527460AA84}
|
|
*/
|
|
static struct bt_uuid_128 smp_bt_svc_uuid = BT_UUID_INIT_128(
|
|
0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86,
|
|
0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d);
|
|
|
|
/* SMP characteristic; used for both requests and responses.
|
|
* {DA2E7828-FBCE-4E01-AE9E-261174997C48}
|
|
*/
|
|
static struct bt_uuid_128 smp_bt_chr_uuid = BT_UUID_INIT_128(
|
|
0x48, 0x7c, 0x99, 0x74, 0x11, 0x26, 0x9e, 0xae,
|
|
0x01, 0x4e, 0xce, 0xfb, 0x28, 0x78, 0x2e, 0xda);
|
|
|
|
/**
|
|
* Write handler for the SMP characteristic; processes an incoming SMP request.
|
|
*/
|
|
static ssize_t smp_bt_chr_write(struct bt_conn *conn,
|
|
const struct bt_gatt_attr *attr,
|
|
const void *buf, u16_t len, u16_t offset,
|
|
u8_t flags)
|
|
{
|
|
struct smp_bt_user_data *ud;
|
|
struct net_buf *nb;
|
|
|
|
nb = mcumgr_buf_alloc();
|
|
net_buf_add_mem(nb, buf, len);
|
|
|
|
ud = net_buf_user_data(nb);
|
|
ud->conn = bt_conn_ref(conn);
|
|
|
|
zephyr_smp_rx_req(&smp_bt_transport, nb);
|
|
|
|
return len;
|
|
}
|
|
|
|
static void smp_bt_ccc_changed(const struct bt_gatt_attr *attr, u16_t value)
|
|
{
|
|
}
|
|
|
|
static struct bt_gatt_attr smp_bt_attrs[] = {
|
|
/* SMP Primary Service Declaration */
|
|
BT_GATT_PRIMARY_SERVICE(&smp_bt_svc_uuid),
|
|
|
|
BT_GATT_CHARACTERISTIC(&smp_bt_chr_uuid.uuid,
|
|
BT_GATT_CHRC_WRITE_WITHOUT_RESP |
|
|
BT_GATT_CHRC_NOTIFY,
|
|
#ifdef CONFIG_MCUMGR_SMP_BT_AUTHEN
|
|
BT_GATT_PERM_WRITE_AUTHEN,
|
|
#else
|
|
BT_GATT_PERM_WRITE,
|
|
#endif
|
|
NULL, smp_bt_chr_write, NULL),
|
|
BT_GATT_CCC(smp_bt_ccc_changed,
|
|
#ifdef CONFIG_MCUMGR_SMP_BT_AUTHEN
|
|
BT_GATT_PERM_READ_AUTHEN |
|
|
BT_GATT_PERM_WRITE_AUTHEN),
|
|
#else
|
|
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
|
|
#endif
|
|
};
|
|
|
|
static struct bt_gatt_service smp_bt_svc = BT_GATT_SERVICE(smp_bt_attrs);
|
|
|
|
/**
|
|
* Transmits an SMP response over the specified Bluetooth connection.
|
|
*/
|
|
static int smp_bt_tx_rsp(struct bt_conn *conn, const void *data, u16_t len)
|
|
{
|
|
return bt_gatt_notify(conn, smp_bt_attrs + 2, data, len);
|
|
}
|
|
|
|
/**
|
|
* Extracts the Bluetooth connection from a net_buf's user data.
|
|
*/
|
|
static struct bt_conn *smp_bt_conn_from_pkt(const struct net_buf *nb)
|
|
{
|
|
struct smp_bt_user_data *ud = net_buf_user_data(nb);
|
|
|
|
if (!ud->conn) {
|
|
return NULL;
|
|
}
|
|
|
|
return bt_conn_ref(ud->conn);
|
|
}
|
|
|
|
/**
|
|
* Calculates the maximum fragment size to use when sending the specified
|
|
* response packet.
|
|
*/
|
|
static u16_t smp_bt_get_mtu(const struct net_buf *nb)
|
|
{
|
|
struct bt_conn *conn;
|
|
u16_t mtu;
|
|
|
|
conn = smp_bt_conn_from_pkt(nb);
|
|
if (conn == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
mtu = bt_gatt_get_mtu(conn);
|
|
bt_conn_unref(conn);
|
|
|
|
/* Account for the three-byte notification header. */
|
|
return mtu - 3;
|
|
}
|
|
|
|
static void smp_bt_ud_free(void *ud)
|
|
{
|
|
struct smp_bt_user_data *user_data = ud;
|
|
|
|
if (user_data->conn) {
|
|
bt_conn_unref(user_data->conn);
|
|
user_data->conn = NULL;
|
|
}
|
|
}
|
|
|
|
static int smp_bt_ud_copy(struct net_buf *dst, const struct net_buf *src)
|
|
{
|
|
struct smp_bt_user_data *src_ud = net_buf_user_data(src);
|
|
struct smp_bt_user_data *dst_ud = net_buf_user_data(dst);
|
|
|
|
if (src_ud->conn) {
|
|
dst_ud->conn = bt_conn_ref(src_ud->conn);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Transmits the specified SMP response.
|
|
*/
|
|
static int smp_bt_tx_pkt(struct zephyr_smp_transport *zst, struct net_buf *nb)
|
|
{
|
|
struct bt_conn *conn;
|
|
int rc;
|
|
|
|
conn = smp_bt_conn_from_pkt(nb);
|
|
if (conn == NULL) {
|
|
rc = -1;
|
|
} else {
|
|
rc = smp_bt_tx_rsp(conn, nb->data, nb->len);
|
|
bt_conn_unref(conn);
|
|
}
|
|
|
|
smp_bt_ud_free(net_buf_user_data(nb));
|
|
mcumgr_buf_free(nb);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int smp_bt_register(void)
|
|
{
|
|
return bt_gatt_service_register(&smp_bt_svc);
|
|
}
|
|
|
|
int smp_bt_unregister(void)
|
|
{
|
|
return bt_gatt_service_unregister(&smp_bt_svc);
|
|
}
|
|
|
|
static int smp_bt_init(struct device *dev)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
|
|
zephyr_smp_transport_init(&smp_bt_transport, smp_bt_tx_pkt,
|
|
smp_bt_get_mtu, smp_bt_ud_copy,
|
|
smp_bt_ud_free);
|
|
return 0;
|
|
}
|
|
|
|
SYS_INIT(smp_bt_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|