From: Szymon Janc <szymon.janc@codecoup.pl>
To: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: "linux-bluetooth@vger.kernel.org" <linux-bluetooth@vger.kernel.org>
Subject: Re: [PATCH] Add support for requiring min key size for access GATT characteristics
Date: Tue, 20 Mar 2018 10:10:31 +0100 [thread overview]
Message-ID: <3405591.sIV7NVuiC8@ix> (raw)
In-Reply-To: <CABBYNZLQGEEQujx49DhrBaoOGyUPQ_Pqv-MdFA9o3T0=5WzLRg@mail.gmail.com>
Hi Luiz,
On Tuesday, 20 March 2018 09:01:09 CET Luiz Augusto von Dentz wrote:
> Hi Szymon,
>
> On Mon, Mar 19, 2018 at 5:06 PM, Szymon Janc <szymon.janc@codecoup.pl>
wrote:
> > This allows to configure bluetoothd to require minimum encryption key
> > size when accessing GATT server characteristics. It is a global
> > configuration option affecting whole GATT database.
>
> I guess this is just to pass some GATT testing, I really wonder why
> such a thing would be mandatory if there isn't any way to influence
> the key size on SMP, or is there? If you would have some extra time it
> would be great to have unit tests for the affected tests of the
> testing spec.
Yes, there are multiple tests affected by this. But I don't see a reason why
not to have option to enforce minimal key size as defined by spec. On SMP
level this is basically minimum of both sides. And I don't think we should
enforce this on pairing as this would have to result in Pairing Failed and
thus link disconnection.
>
> > ---
> >
> > peripheral/gatt.c | 2 +-
> > src/adapter.c | 44
> > +++++++++++++++++++++++++++++++-------------
> > src/device.c | 14 ++++++++++++--
> > src/device.h | 1 +
> > src/hcid.h | 2 ++
> > src/main.c | 10 ++++++++++
> > src/main.conf | 5 +++++
> > src/shared/gatt-server.c | 43 ++++++++++++++++++++++++++++++++++++-------
> > src/shared/gatt-server.h | 6 +++++-
> > tools/btgatt-server.c | 2 +-
> > unit/test-gatt.c | 2 +-
> > 11 files changed, 105 insertions(+), 26 deletions(-)
> >
> > diff --git a/peripheral/gatt.c b/peripheral/gatt.c
> > index 5ae19a8e5..08541c424 100644
> > --- a/peripheral/gatt.c
> > +++ b/peripheral/gatt.c
> > @@ -128,7 +128,7 @@ static struct gatt_conn *gatt_conn_new(int fd)
> >
> > bt_att_set_security(conn->att, BT_SECURITY_MEDIUM);
> >
> > - conn->gatt = bt_gatt_server_new(gatt_db, conn->att, mtu);
> > + conn->gatt = bt_gatt_server_new(gatt_db, conn->att, mtu, 0);
> >
> > if (!conn->gatt) {
> >
> > fprintf(stderr, "Failed to create GATT server\n");
> > bt_att_unref(conn->att);
> >
> > diff --git a/src/adapter.c b/src/adapter.c
> > index 6d7d61504..c8e365479 100644
> > --- a/src/adapter.c
> > +++ b/src/adapter.c
> >
> > @@ -3441,25 +3441,26 @@ failed:
> > return ltk;
> >
> > }
> >
> > -static GSList *get_ltk_info(GKeyFile *key_file, const char *peer,
> > +struct smp_ltk_info *get_ltk_info(GKeyFile *key_file, const char *peer,
> > + uint8_t
> > bdaddr_type) +{
> > + DBG("%s", peer);
> > +
> > + return get_ltk(key_file, peer, bdaddr_type, "LongTermKey");
> > +}
> > +
> > +struct smp_ltk_info *get_slave_ltk_info(GKeyFile *key_file, const char
> > *peer,>
> > uint8_t
> > bdaddr_type)
> >
> > {
> >
> > struct smp_ltk_info *ltk;
> >
> > - GSList *l = NULL;
> >
> > DBG("%s", peer);
> >
> > - ltk = get_ltk(key_file, peer, bdaddr_type, "LongTermKey");
> > - if (ltk)
> > - l = g_slist_append(l, ltk);
> > -
> >
> > ltk = get_ltk(key_file, peer, bdaddr_type, "SlaveLongTermKey");
> >
> > - if (ltk) {
> > + if (ltk)
> >
> > ltk->master = false;
> >
> > - l = g_slist_append(l, ltk);
> > - }
> >
> > - return l;
> > + return ltk;
> >
> > }
> >
> > static struct irk_info *get_irk_info(GKeyFile *key_file, const char
> > *peer,
> >
> > @@ -4019,7 +4020,9 @@ static void load_devices(struct btd_adapter
> > *adapter)
> >
> > char filename[PATH_MAX];
> > GKeyFile *key_file;
> > struct link_key_info *key_info;
> >
> > - GSList *list, *ltk_info;
> > + struct smp_ltk_info *ltk_info;
> > + struct smp_ltk_info *slave_ltk_info;
> > + GSList *list;
> >
> > struct irk_info *irk_info;
> > struct conn_param *param;
> > uint8_t bdaddr_type;
> >
> > @@ -4044,7 +4047,13 @@ static void load_devices(struct btd_adapter
> > *adapter)>
> > bdaddr_type = get_le_addr_type(key_file);
> >
> > ltk_info = get_ltk_info(key_file, entry->d_name,
> > bdaddr_type);
> >
> > - ltks = g_slist_concat(ltks, ltk_info);
> > + if (ltk_info)
> > + ltks = g_slist_append(ltks, ltk_info);
> > +
> > + slave_ltk_info = get_slave_ltk_info(key_file,
> > entry->d_name, +
> > bdaddr_type); + if (slave_ltk_info)
> > + ltks = g_slist_append(ltks, slave_ltk_info);
> >
> > irk_info = get_irk_info(key_file, entry->d_name,
> > bdaddr_type);
> > if (irk_info)
> >
> > @@ -4079,9 +4088,16 @@ device_exist:
> > device_set_bonded(device, BDADDR_BREDR);
> >
> > }
> >
> > - if (ltk_info) {
> > + if (ltk_info || slave_ltk_info) {
> >
> > device_set_paired(device, bdaddr_type);
> > device_set_bonded(device, bdaddr_type);
> >
> > +
> > + if (ltk_info)
> > + device_set_ltk_enc_size(device,
> > +
> > ltk_info->enc_size); + else if (slave_ltk_info)
> > + device_set_ltk_enc_size(device,
> > + slave_ltk_info->enc_size);
> >
> > }
> >
> > free:
> > @@ -7464,6 +7480,8 @@ static void new_long_term_key_callback(uint16_t
> > index, uint16_t length,>
> > device_set_bonded(device, addr->type);
> >
> > }
> >
> > + device_set_ltk_enc_size(device, ev->key.enc_size);
> > +
> >
> > bonding_complete(adapter, &addr->bdaddr, addr->type, 0);
> >
> > }
> >
> > diff --git a/src/device.c b/src/device.c
> > index 7c7196ca1..64b05d2f4 100644
> > --- a/src/device.c
> > +++ b/src/device.c
> > @@ -243,6 +243,7 @@ struct btd_device {
> >
> > struct csrk_info *local_csrk;
> > struct csrk_info *remote_csrk;
> >
> > + uint8_t ltk_enc_size;
> >
> > sdp_list_t *tmp_records;
> >
> > @@ -1460,6 +1461,11 @@ bool device_is_disconnecting(struct btd_device
> > *device)>
> > return device->disconn_timer > 0;
> >
> > }
> >
> > +void device_set_ltk_enc_size(struct btd_device *device, uint8_t enc_size)
> > +{
> > + device->ltk_enc_size = enc_size;
> > +}
> > +
> >
> > static void device_set_auto_connect(struct btd_device *device, gboolean
> > enable) {
> >
> > char addr[18];
> >
> > @@ -4834,11 +4840,15 @@ static void gatt_server_init(struct btd_device
> > *device, struct gatt_db *db)>
> > gatt_server_cleanup(device);
> >
> > - device->server = bt_gatt_server_new(db, device->att,
> > device->att_mtu); - if (!device->server)
> > + device->server = bt_gatt_server_new(db, device->att,
> > device->att_mtu, +
> > main_opts.min_enc_key_size); + if (!device->server) {
> >
> > error("Failed to initialize bt_gatt_server");
> >
> > + return;
> > + }
> >
> > bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL);
> >
> > + bt_gatt_server_set_enc_key_size(device->server,
> > device->ltk_enc_size);>
> > }
> >
> > static bool local_counter(uint32_t *sign_cnt, void *user_data)
> >
> > diff --git a/src/device.h b/src/device.h
> > index bc046f780..306c813fc 100644
> > --- a/src/device.h
> > +++ b/src/device.h
> > @@ -130,6 +130,7 @@ void device_add_connection(struct btd_device *dev,
> > uint8_t bdaddr_type);>
> > void device_remove_connection(struct btd_device *device, uint8_t
> > bdaddr_type); void device_request_disconnect(struct btd_device *device,
> > DBusMessage *msg); bool device_is_disconnecting(struct btd_device
> > *device);
> >
> > +void device_set_ltk_enc_size(struct btd_device *device, uint8_t
> > enc_size);
> >
> > typedef void (*disconnect_watch) (struct btd_device *device, gboolean
> > removal,>
> > void *user_data);
> >
> > diff --git a/src/hcid.h b/src/hcid.h
> > index 62e2bd606..2c2b89d9c 100644
> > --- a/src/hcid.h
> > +++ b/src/hcid.h
> > @@ -54,6 +54,8 @@ struct main_opts {
> >
> > bt_mode_t mode;
> > bt_gatt_cache_t gatt_cache;
> >
> > +
> > + uint8_t min_enc_key_size;
> >
> > };
> >
> > extern struct main_opts main_opts;
> >
> > diff --git a/src/main.c b/src/main.c
> > index 21f0b14a4..29a78e64c 100644
> > --- a/src/main.c
> > +++ b/src/main.c
> > @@ -407,6 +407,16 @@ static void parse_config(GKeyFile *config)
> >
> > main_opts.gatt_cache = parse_gatt_cache(str);
> >
> > + val = g_key_file_get_integer(config, "GATT",
> > + "MinEncKeySize", &err);
> > + if (err) {
> > + DBG("%s", err->message);
> > + g_clear_error(&err);
> > + } else {
> > + DBG("min_enc_key_size=%d", val);
> > + main_opts.min_enc_key_size = val;
> > + }
> > +
> >
> > g_free(str);
> >
> > }
> >
> > diff --git a/src/main.conf b/src/main.conf
> > index 21986b386..cbae32ec5 100644
> > --- a/src/main.conf
> > +++ b/src/main.conf
> > @@ -77,6 +77,11 @@
> >
> > # Default: always
> > #Cache = always
> >
> > +# Minimum required Encryption Key Size for accessing secured
> > characteristics. +# Possible values: 0 and 7-16. 0 means don't care.
> > +# Defaults to 0
> > +# MinEncKeySize = 0
> > +
> >
> > [Policy]
> > #
> > # The ReconnectUUIDs defines the set of remote services that should try
> >
> > diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
> > index faa56abeb..cf88d72df 100644
> > --- a/src/shared/gatt-server.c
> > +++ b/src/shared/gatt-server.c
> > @@ -103,6 +103,9 @@ struct bt_gatt_server {
> >
> > unsigned int prep_write_id;
> > unsigned int exec_write_id;
> >
> > + uint8_t min_enc_size;
> > + uint8_t enc_size;
> > +
> >
> > struct queue *prep_queue;
> > unsigned int max_prep_queue_len;
> >
> > @@ -379,6 +382,12 @@ done:
> > process_read_by_type(op);
> >
> > }
> >
> > +void bt_gatt_server_set_enc_key_size(struct bt_gatt_server *server,
> > + uint8_t
> > size) +{
> > + server->enc_size = size;
> > +}
>
> I would prefer we would store the key size on bt_att if possible, then
> perhaps return it with bt_att_get_security.
hmm OK, I could do that.
>
> > static uint8_t check_permissions(struct bt_gatt_server *server,
> >
> > struct gatt_db_attribute *attr, uint32_t
> > mask)
> >
> > {
> >
> > @@ -398,14 +407,32 @@ static uint8_t check_permissions(struct
> > bt_gatt_server *server,>
> > return 0;
> >
> > security = bt_att_get_security(server->att);
> >
> > - if (perm & BT_ATT_PERM_SECURE && security < BT_ATT_SECURITY_FIPS)
> > - return BT_ATT_ERROR_AUTHENTICATION;
> > + if (perm & BT_ATT_PERM_SECURE) {
> > + if (security < BT_ATT_SECURITY_FIPS)
> > + return BT_ATT_ERROR_AUTHENTICATION;
> > +
> > + if (server->min_enc_size &&
> > + server->min_enc_size > server->enc_size)
> > + return
> > BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE; + }
> > +
> > + if (perm & BT_ATT_PERM_AUTHEN) {
> > + if (security < BT_ATT_SECURITY_HIGH)
> > + return BT_ATT_ERROR_AUTHENTICATION;
> >
> > - if (perm & BT_ATT_PERM_AUTHEN && security < BT_ATT_SECURITY_HIGH)
> > - return BT_ATT_ERROR_AUTHENTICATION;
> > + if (server->min_enc_size &&
> > + server->min_enc_size > server->enc_size)
> > + return
> > BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE; + }
> >
> > - if (perm & BT_ATT_PERM_ENCRYPT && security <
> > BT_ATT_SECURITY_MEDIUM) - return
> > BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION;
> > + if (perm & BT_ATT_PERM_ENCRYPT) {
> > + if (security < BT_ATT_SECURITY_MEDIUM)
> > + return BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION;
> > +
> > + if (server->min_enc_size &&
> > + server->min_enc_size > server->enc_size)
> > + return
> > BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE; + }
> >
> > return 0;
> >
> > }
> >
> > @@ -1481,7 +1508,8 @@ static bool gatt_server_register_att_handlers(struct
> > bt_gatt_server *server)>
> > }
> >
> > struct bt_gatt_server *bt_gatt_server_new(struct gatt_db *db,
> >
> > - struct bt_att *att, uint16_t mtu)
> > + struct bt_att *att, uint16_t mtu,
> > + uint8_t min_enc_size)
> >
> > {
> >
> > struct bt_gatt_server *server;
> >
> > @@ -1494,6 +1522,7 @@ struct bt_gatt_server *bt_gatt_server_new(struct
> > gatt_db *db,>
> > server->mtu = MAX(mtu, BT_ATT_DEFAULT_LE_MTU);
> > server->max_prep_queue_len = DEFAULT_MAX_PREP_QUEUE_LEN;
> > server->prep_queue = queue_new();
> >
> > + server->min_enc_size = min_enc_size;
> >
> > if (!gatt_server_register_att_handlers(server)) {
> >
> > bt_gatt_server_free(server);
> >
> > diff --git a/src/shared/gatt-server.h b/src/shared/gatt-server.h
> > index 74a6c721e..6bf178a9b 100644
> > --- a/src/shared/gatt-server.h
> > +++ b/src/shared/gatt-server.h
> > @@ -26,7 +26,8 @@
> >
> > struct bt_gatt_server;
> >
> > struct bt_gatt_server *bt_gatt_server_new(struct gatt_db *db,
> >
> > - struct bt_att *att, uint16_t mtu);
> > + struct bt_att *att, uint16_t mtu,
> > + uint8_t min_enc_size);
> >
> > uint16_t bt_gatt_server_get_mtu(struct bt_gatt_server *server);
> >
> > struct bt_gatt_server *bt_gatt_server_ref(struct bt_gatt_server *server);
> >
> > @@ -51,3 +52,6 @@ bool bt_gatt_server_send_indication(struct
> > bt_gatt_server *server,>
> > bt_gatt_server_conf_func_t
> > callback,
> > void *user_data,
> > bt_gatt_server_destroy_func_t
> > destroy);
> >
> > +
> > +void bt_gatt_server_set_enc_key_size(struct bt_gatt_server *server,
> > + uint8_t
> > size); diff --git a/tools/btgatt-server.c b/tools/btgatt-server.c
> > index fadaff2ad..89812bd75 100644
> > --- a/tools/btgatt-server.c
> > +++ b/tools/btgatt-server.c
> > @@ -583,7 +583,7 @@ static struct server *server_create(int fd, uint16_t
> > mtu, bool hr_visible)>
> > goto fail;
> >
> > }
> >
> > - server->gatt = bt_gatt_server_new(server->db, server->att, mtu);
> > + server->gatt = bt_gatt_server_new(server->db, server->att, mtu,
> > 0);
> >
> > if (!server->gatt) {
> >
> > fprintf(stderr, "Failed to create GATT server\n");
> > goto fail;
> >
> > diff --git a/unit/test-gatt.c b/unit/test-gatt.c
> > index 5d79e94c0..c7e28f865 100644
> > --- a/unit/test-gatt.c
> > +++ b/unit/test-gatt.c
> > @@ -667,7 +667,7 @@ static struct context *create_context(uint16_t mtu,
> > gconstpointer data)>
> > g_assert(context->server_db);
> >
> > context->server = bt_gatt_server_new(context->server_db,
> >
> > - context->att,
> > mtu);
> > + context->att, mtu,
> > 0);>
> > g_assert(context->server);
> >
> > bt_gatt_server_set_debug(context->server, print_debug,
> >
> > --
> > 2.14.3
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> > in the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
--
pozdrawiam
Szymon Janc
prev parent reply other threads:[~2018-03-20 9:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-19 15:06 [PATCH] Add support for requiring min key size for access GATT characteristics Szymon Janc
2018-03-20 8:01 ` Luiz Augusto von Dentz
2018-03-20 9:10 ` Szymon Janc [this message]
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=3405591.sIV7NVuiC8@ix \
--to=szymon.janc@codecoup.pl \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
/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