From: Dagan Martinez <dmartinez@starry.com>
To: linux-bluetooth@vger.kernel.org
Cc: Dagan Martinez <dmartinez@starry.com>
Subject: [PATCH BlueZ v3 1/2] gatt: Allow GATT server to dicate CCC permissions
Date: Thu, 30 Sep 2021 11:08:18 -0400 [thread overview]
Message-ID: <20210930150819.34270-2-dmartinez@starry.com> (raw)
In-Reply-To: <20210930150819.34270-1-dmartinez@starry.com>
Allow a GATT server to impose permissions/restrictions on a CCC by
setting additional `X-notify` and `X-indicate` permissions on its
associated characteristic.
This allows a developer to require encryption/authentication in order
for a GATT client to subscribe to server-initiated updates.
Test procedure:
Attempt to read/write with a "low" security level on an unprotected CCC
using gatttool, and succeed
Attempt to READ with a "low" security level on an protected CCC
using gatttool, and succeed
Attempt to WRITE with a "low" security level on an protected CCC
using gatttool, and fail
Attempt to read/write while paired on a protected CCC using
`bluetoothctl`, and succeed
---
src/gatt-database.c | 42 ++++++++++++++++++++++++++++++++++++++----
src/shared/att-types.h | 4 ++++
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 68f411ba4..fd4a39166 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -1060,17 +1060,33 @@ service_add_ccc(struct gatt_db_attribute *service,
struct btd_gatt_database *database,
btd_gatt_database_ccc_write_t write_callback,
void *user_data,
+ uint32_t parent_permissions,
btd_gatt_database_destroy_t destroy)
{
struct gatt_db_attribute *ccc;
struct ccc_cb_data *ccc_cb;
bt_uuid_t uuid;
+ uint32_t permissions;
ccc_cb = new0(struct ccc_cb_data, 1);
+ /*
+ * Provide a way for the permissions on a characteristic to dictate
+ * the permissions on the CCC
+ */
+ permissions = BT_ATT_PERM_READ | BT_ATT_PERM_WRITE;
+
+ if (parent_permissions & BT_ATT_PERM_SERVER_INITIATED_UPDATE_ENCRYPT)
+ permissions |= BT_ATT_PERM_WRITE_ENCRYPT;
+
+ if (parent_permissions & BT_ATT_PERM_SERVER_INITIATED_UPDATE_AUTHEN)
+ permissions |= BT_ATT_PERM_WRITE_AUTHEN;
+
+ if (parent_permissions & BT_ATT_PERM_SERVER_INITIATED_UPDATE_SECURE)
+ permissions |= BT_ATT_PERM_WRITE_SECURE;
+
bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
- ccc = gatt_db_service_add_descriptor(service, &uuid,
- BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+ ccc = gatt_db_service_add_descriptor(service, &uuid, permissions,
gatt_ccc_read_cb, gatt_ccc_write_cb, database);
if (!ccc) {
error("Failed to create CCC entry in database");
@@ -1227,7 +1243,7 @@ static void populate_gatt_service(struct btd_gatt_database *database)
NULL, NULL, database);
database->svc_chngd_ccc = service_add_ccc(service, database, NULL, NULL,
- NULL);
+ 0, NULL);
bt_uuid16_create(&uuid, GATT_CHARAC_CLI_FEAT);
database->cli_feat = gatt_db_service_add_characteristic(service,
@@ -1690,6 +1706,24 @@ static bool parse_chrc_flags(DBusMessageIter *array, uint8_t *props,
*perm |= BT_ATT_PERM_WRITE | BT_ATT_PERM_WRITE_SECURE;
} else if (!strcmp("authorize", flag)) {
*req_prep_authorization = true;
+ } else if (!strcmp("encrypt-notify", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_ENCRYPT;
+ *props |= BT_GATT_CHRC_PROP_NOTIFY;
+ } else if (!strcmp("encrypt-authenticated-notify", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_AUTHEN;
+ *props |= BT_GATT_CHRC_PROP_NOTIFY;
+ } else if (!strcmp("secure-notify", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_SECURE;
+ *props |= BT_GATT_CHRC_PROP_NOTIFY;
+ } else if (!strcmp("encrypt-indicate", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_ENCRYPT;
+ *props |= BT_GATT_CHRC_PROP_INDICATE;
+ } else if (!strcmp("encrypt-authenticated-indicate", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_AUTHEN;
+ *props |= BT_GATT_CHRC_PROP_INDICATE;
+ } else if (!strcmp("secure-indicate", flag)) {
+ *perm |= BT_ATT_PERM_SERVER_INITIATED_UPDATE_SECURE;
+ *props |= BT_GATT_CHRC_PROP_INDICATE;
} else {
error("Invalid characteristic flag: %s", flag);
return false;
@@ -2796,7 +2830,7 @@ static bool database_add_ccc(struct external_service *service,
return true;
chrc->ccc = service_add_ccc(service->attrib, service->app->database,
- ccc_write_cb, chrc, NULL);
+ ccc_write_cb, chrc, chrc->perm, NULL);
if (!chrc->ccc) {
error("Failed to create CCC entry for characteristic");
return false;
diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index a08b24155..eb5def503 100644
--- a/src/shared/att-types.h
+++ b/src/shared/att-types.h
@@ -137,6 +137,10 @@ struct bt_att_pdu_error_rsp {
BT_ATT_PERM_WRITE_AUTHEN | \
BT_ATT_PERM_WRITE_ENCRYPT | \
BT_ATT_PERM_WRITE_SECURE)
+/* Permissions to be applied to the CCC*/
+#define BT_ATT_PERM_SERVER_INITIATED_UPDATE_ENCRYPT 0x0400
+#define BT_ATT_PERM_SERVER_INITIATED_UPDATE_AUTHEN 0x0800
+#define BT_ATT_PERM_SERVER_INITIATED_UPDATE_SECURE 0x1000
/* GATT Characteristic Properties Bitfield values */
#define BT_GATT_CHRC_PROP_BROADCAST 0x01
--
2.31.1
next prev parent reply other threads:[~2021-09-30 15:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-30 15:08 [PATCH BlueZ v3 0/2] Optionally require security for notify/indicate Dagan Martinez
2021-09-30 15:08 ` Dagan Martinez [this message]
2021-09-30 20:25 ` [PATCH BlueZ v3 1/2] gatt: Allow GATT server to dicate CCC permissions Luiz Augusto von Dentz
2021-09-30 15:08 ` [PATCH BlueZ v3 2/2] doc/gatt-api: Add 'X-notify`/`X-indicate` Dagan Martinez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210930150819.34270-2-dmartinez@starry.com \
--to=dmartinez@starry.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).