This is an automated email from the ASF dual-hosted git repository.

sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new bfde0dce9 nimble/host: inherit characteristic security requirements in 
CCCD
bfde0dce9 is described below

commit bfde0dce9e031a2a660f6a940549b5f18e1628da
Author: Gerard Marull-Paretas <[email protected]>
AuthorDate: Tue Jul 7 17:55:20 2026 +0200

    nimble/host: inherit characteristic security requirements in CCCD
    
    The CCCD was registered with plain read/write permissions regardless of
    the security declared on its characteristic, so any unencrypted client
    could subscribe and receive an otherwise protected value via
    notifications/indications, bypassing its protection.
    
    The Core Specification leaves CCCD write permissions to the
    implementation and anticipates gating them (Vol 3, Part G, 3.3.3.3;
    Vol 3, Part F, 3.2.5). Zephyr already enforces this: the CCC carries
    its own security permissions, and the value's read security is checked
    in the notify/indicate send path. NimBLE auto-generates the CCCD with
    no per-descriptor permission API, so inherit the characteristic's
    security requirements to achieve the same protection.
    
    Require for the CCCD write the union of the characteristic's read and
    write encryption/authentication flags, derived via
    ble_gatts_att_flags_from_chr_flags to keep a single mapping point, and
    propagate min_key_size as well. Authorization flags are deliberately
    not inherited: ble_att_svr_check_perms does not enforce authorization
    (left to the access callback, which for the CCCD is stack-internal),
    and the flag alone would activate the min_key_size check, rejecting
    every CCCD write on an unencrypted link. CCCD reads remain
    unprotected, per Vol 3, Part G, 3.3.3.3.
    
    Signed-off-by: Gerard Marull-Paretas <[email protected]>
---
 nimble/host/src/ble_gatts.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c
index 8d7897bec..ac5576f6d 100644
--- a/nimble/host/src/ble_gatts.c
+++ b/nimble/host/src/ble_gatts.c
@@ -830,11 +830,29 @@ ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t 
attr_handle,
 }
 
 static int
-ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
+ble_gatts_register_clt_cfg_dsc(const struct ble_gatt_chr_def *chr, uint16_t 
*att_handle)
 {
+    uint8_t chr_att_flags;
+    uint8_t att_flags;
     int rc;
 
-    rc = ble_att_svr_register(uuid_ccc, BLE_ATT_F_READ | BLE_ATT_F_WRITE, 0,
+    /* Writing the CCCD enables notifications/indications of the
+     * characteristic value, so require the same encryption/authentication
+     * level as the characteristic itself. Authorization is not inherited:
+     * the stack cannot enforce it on the internal CCCD access callback,
+     * and its flag alone would wrongly activate the key-size check.
+     */
+    chr_att_flags = ble_gatts_att_flags_from_chr_flags(chr->flags);
+
+    att_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE;
+    if (chr_att_flags & (BLE_ATT_F_READ_ENC | BLE_ATT_F_WRITE_ENC)) {
+        att_flags |= BLE_ATT_F_WRITE_ENC;
+    }
+    if (chr_att_flags & (BLE_ATT_F_READ_AUTHEN | BLE_ATT_F_WRITE_AUTHEN)) {
+        att_flags |= BLE_ATT_F_WRITE_AUTHEN;
+    }
+
+    rc = ble_att_svr_register(uuid_ccc, att_flags, chr->min_key_size,
                               att_handle, ble_gatts_clt_cfg_access, NULL);
     if (rc != 0) {
         return rc;
@@ -958,7 +976,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
     }
 
     if (ble_gatts_chr_clt_cfg_allowed(chr) != 0) {
-        rc = ble_gatts_register_clt_cfg_dsc(&dsc_handle);
+        rc = ble_gatts_register_clt_cfg_dsc(chr, &dsc_handle);
         if (rc != 0) {
             return rc;
         }

Reply via email to