Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/zephyr/bluetooth/gatt.h
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,7 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn,
* Read include service attribute value from local database storing the result
* into buffer after encoding it.
* @note Only use this with attributes which user_data is a ``bt_gatt_include``.
* The function returns EINVAL if @p attr or @p attr->user_data is NULL.
*
* @param conn Connection object.
* @param attr Attribute to read.
Expand Down
14 changes: 14 additions & 0 deletions include/zephyr/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ extern "C" {
*/
#define BT_L2CAP_ECRED_MIN_MPS 64

/** @brief L2CAP maximum MTU
*
* The maximum MTU for an L2CAP Based Connection. This is the same with or without ECRED. This
* requirement is taken from text in Core 3.A.4.22 and 3.A.4.26 v6.0.
*/
#define BT_L2CAP_MAX_MTU UINT16_MAX

/** @brief L2CAP maximum MPS
*
* The maximum MPS for an L2CAP Based Connection. This is the same with or without ECRED. This
* requirement is taken from text in Core 3.A.4.22 and 3.A.4.26 v6.0.
*/
#define BT_L2CAP_MAX_MPS 65533

/** @brief The maximum number of channels in ECRED L2CAP signaling PDUs
*
* Currently, this is the maximum number of channels referred to in the
Expand Down
4 changes: 4 additions & 0 deletions subsys/bluetooth/host/gatt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1917,6 +1917,10 @@ ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
if ((attr == NULL) || (attr->user_data == NULL)) {
return -EINVAL;
}

struct bt_gatt_attr *incl = attr->user_data;
uint16_t handle = bt_gatt_attr_get_handle(incl);
struct bt_uuid *uuid = incl->user_data;
Expand Down
66 changes: 56 additions & 10 deletions subsys/bluetooth/host/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
#define CHAN_RX(_w) CONTAINER_OF(_w, struct bt_l2cap_le_chan, rx_work)

#define L2CAP_LE_MIN_MTU 23
#define L2CAP_LE_MIN_MPS 23

Check notice on line 50 in subsys/bluetooth/host/l2cap.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/host/l2cap.c:50 -#define L2CAP_LE_MIN_MPS 23 +#define L2CAP_LE_MIN_MPS 23
#define L2CAP_LE_MAX_CREDITS (BT_BUF_ACL_RX_COUNT - 1)

#define L2CAP_LE_CID_DYN_START 0x0040
Expand Down Expand Up @@ -1478,11 +1479,6 @@

LOG_DBG("psm 0x%02x scid 0x%04x mtu %u mps %u credits %u", psm, scid, mtu, mps, credits);

if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MTU) {
LOG_ERR("Invalid LE-Conn Req params: mtu %u mps %u", mtu, mps);
return;
}

buf = l2cap_create_le_sig_pdu(BT_L2CAP_LE_CONN_RSP, ident,
sizeof(*rsp));
if (!buf) {
Expand All @@ -1492,6 +1488,16 @@
rsp = net_buf_add(buf, sizeof(*rsp));
(void)memset(rsp, 0, sizeof(*rsp));

/* Validate parameters. Requirements are from Core Spec v6.0, Vol 3.A.4.22. Valid credit
* range is from 0 to UINT16_MAX, thus no credit validation is needed.
*/
if (!IN_RANGE(mtu, L2CAP_LE_MIN_MTU, BT_L2CAP_MAX_MTU) ||
!IN_RANGE(mps, L2CAP_LE_MIN_MPS, BT_L2CAP_MAX_MPS)) {
LOG_ERR("Invalid le conn req params: mtu %u mps %u", mtu, mps);
result = BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
goto rsp;
}

/* Check if there is a server registered */
server = bt_l2cap_server_lookup_psm(psm);
if (!server) {
Expand Down Expand Up @@ -1577,8 +1583,12 @@

LOG_DBG("psm 0x%02x mtu %u mps %u credits %u", psm, mtu, mps, credits);

if (mtu < BT_L2CAP_ECRED_MIN_MTU || mps < BT_L2CAP_ECRED_MIN_MTU) {
LOG_ERR("Invalid ecred conn req params. mtu %u mps %u", mtu, mps);
/* Validate parameters. Requirements are from Core Spec v6.0, Vol 3.A.4.25. */
if (!IN_RANGE(mtu, BT_L2CAP_ECRED_MIN_MTU, BT_L2CAP_MAX_MTU) ||
!IN_RANGE(mps, BT_L2CAP_ECRED_MIN_MPS, BT_L2CAP_MAX_MPS) ||
!IN_RANGE(credits, BT_L2CAP_ECRED_CREDITS_MIN, BT_L2CAP_ECRED_CREDITS_MAX)) {
LOG_ERR("Invalid le ecred conn req params: mtu %u mps %u credits %u", mtu, mps,
credits);
result = BT_L2CAP_LE_ERR_INVALID_PARAMS;
goto response;
}
Expand Down Expand Up @@ -1685,7 +1695,7 @@
mtu = sys_le16_to_cpu(req->mtu);
mps = sys_le16_to_cpu(req->mps);

if (mps < BT_L2CAP_ECRED_MIN_MTU) {
if (mps < BT_L2CAP_ECRED_MIN_MPS) {
result = BT_L2CAP_RECONF_OTHER_UNACCEPT;
goto response;
}
Expand Down Expand Up @@ -1981,13 +1991,24 @@

LOG_DBG("dcid 0x%04x", dcid);

/* If a Destination CID is 0x0000, the channel was not
/* Validate parameters before assignment. Requirements are from Core Spec
* v6.0, Vol 3.A.4.26. If a Destination CID is 0x0000, the channel was not
* established.
*/
if (!dcid) {
if (dcid == 0U) {
bt_l2cap_chan_remove(conn, &chan->chan);
bt_l2cap_chan_del(&chan->chan);
continue;
} else if (!L2CAP_LE_CID_IS_DYN(dcid) ||
!IN_RANGE(mtu, BT_L2CAP_ECRED_MIN_MTU, BT_L2CAP_MAX_MTU) ||
!IN_RANGE(mps, BT_L2CAP_ECRED_MIN_MPS, BT_L2CAP_MAX_MPS) ||
!IN_RANGE(credits, BT_L2CAP_ECRED_CREDITS_MIN,
BT_L2CAP_ECRED_CREDITS_MAX)) {
LOG_WRN("Invalid ecred conn rsp params: dcid 0x%04x mtu %u mps %u "
"credits %u. Disconnecting.",
dcid, mtu, mps, credits);
bt_conn_disconnect(conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
return;
}

c = bt_l2cap_le_lookup_tx_cid(conn, dcid);
Expand Down Expand Up @@ -2085,6 +2106,20 @@

switch (result) {
case BT_L2CAP_LE_SUCCESS:
/* Validate parameters on successful connection. Requirements are from Core Spec
* v6.0, Vol 3.A.4.23. Valid credit range is from 0 to UINT16_MAX, thus no credit
* validation is needed.
*/
if ((!L2CAP_LE_CID_IS_DYN(dcid) ||
!IN_RANGE(mtu, L2CAP_LE_MIN_MTU, BT_L2CAP_MAX_MTU) ||
!IN_RANGE(mps, L2CAP_LE_MIN_MPS, BT_L2CAP_MAX_MPS))) {
LOG_WRN("Invalid conn rsp params: dcid 0x%04x mtu %u mps %u. "
"Disconnecting.",
dcid, mtu, mps);
bt_conn_disconnect(conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
return;
}

chan->tx.cid = dcid;
chan->tx.mtu = mtu;
chan->tx.mps = mps;
Expand Down Expand Up @@ -2157,6 +2192,17 @@
cid = sys_le16_to_cpu(ev->cid);
credits = sys_le16_to_cpu(ev->credits);

if (!L2CAP_LE_CID_IS_DYN(cid)) {
LOG_WRN("Can't add credits to non-dynamic channel %p (cid 0x%04x)", &l2cap->chan,
cid);
return;
}

if (credits == 0U) {
LOG_WRN("Ignoring zero credit packet");
return;
}

LOG_DBG("cid 0x%04x credits %u", cid, credits);

chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
Expand Down
3 changes: 3 additions & 0 deletions subsys/bluetooth/host/l2cap_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@
uint16_t credits;
} __packed;

#define BT_L2CAP_ECRED_CREDITS_MIN 1
#define BT_L2CAP_ECRED_CREDITS_MAX UINT16_MAX

Check notice on line 130 in subsys/bluetooth/host/l2cap_internal.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/host/l2cap_internal.h:130 -#define BT_L2CAP_ECRED_CREDITS_MIN 1 -#define BT_L2CAP_ECRED_CREDITS_MAX UINT16_MAX +#define BT_L2CAP_ECRED_CREDITS_MIN 1 +#define BT_L2CAP_ECRED_CREDITS_MAX UINT16_MAX
#define BT_L2CAP_ECRED_CONN_REQ 0x17
struct bt_l2cap_ecred_conn_req {
uint16_t psm;
Expand Down
23 changes: 18 additions & 5 deletions subsys/bluetooth/host/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2555,22 +2555,35 @@
static uint8_t legacy_pairing_random(struct bt_smp *smp)
{
struct bt_conn *conn = smp->chan.chan.conn;
uint8_t tmp[16];
uint8_t tmp[16], cfm_i[16];
int err;

LOG_DBG("");

/* calculate confirmation */
/* calculate LP_CONFIRM_R */
err = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
&conn->le.init_addr, &conn->le.resp_addr, tmp);
if (err) {
return BT_SMP_ERR_UNSPECIFIED;
}

/* calculate LP_CONFIRM_I */
err = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp,
&conn->le.init_addr, &conn->le.resp_addr, cfm_i);
if (err) {

Check notice on line 2573 in subsys/bluetooth/host/smp.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/host/smp.c:2573 - err = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp, - &conn->le.init_addr, &conn->le.resp_addr, cfm_i); + err = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp, &conn->le.init_addr, + &conn->le.resp_addr, cfm_i);
return BT_SMP_ERR_UNSPECIFIED;
}

LOG_DBG("pcnf %s", bt_hex(smp->pcnf, 16));
LOG_DBG("cfm %s", bt_hex(tmp, 16));
LOG_DBG("cfm (remote) %s", bt_hex(tmp, 16));
LOG_DBG("cfm (local) %s", bt_hex(cfm_i, 16));

if (memcmp(smp->pcnf, tmp, sizeof(smp->pcnf))) {
/* Core Specification, Vol 3, Part H, section 2.3.5.5 (Errata ES-24491): If the computed
* LP_CONFIRM_R value is not equal to the received LP_CONFIRM_R value, or the received
* LP_CONFIRM_R value is equal to the LP_CONFIRM_I value, fail pairing.
*/
if (memcmp(smp->pcnf, tmp, sizeof(smp->pcnf)) ||
!memcmp(smp->pcnf, cfm_i, sizeof(smp->pcnf))) {
return BT_SMP_ERR_CONFIRM_FAILED;
}

Expand Down Expand Up @@ -4486,7 +4499,7 @@
}
} else if (!bt_pub_key_is_valid(smp->pkey)) {
LOG_WRN("Received invalid public key");
return BT_SMP_ERR_INVALID_PARAMS;
return BT_SMP_ERR_DHKEY_CHECK_FAILED;
}

if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
Expand Down
2 changes: 1 addition & 1 deletion tests/bsim/bluetooth/host/l2cap/many_conns/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ DEFINE_FLAG_STATIC(flag_l2cap_connected);
#define NUM_PERIPHERALS CONFIG_BT_MAX_CONN
#define L2CAP_CHANS NUM_PERIPHERALS
#define SDU_NUM 1
#define SDU_LEN 10
#define SDU_LEN 23

/* Only one SDU per link will be transmitted */
NET_BUF_POOL_DEFINE(sdu_tx_pool,
Expand Down
Loading