From patchwork Tue Mar 7 22:24:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660006 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E2B1C6FA99 for ; Tue, 7 Mar 2023 22:25:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231139AbjCGWZY (ORCPT ); Tue, 7 Mar 2023 17:25:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231755AbjCGWZB (ORCPT ); Tue, 7 Mar 2023 17:25:01 -0500 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 58F0D90095 for ; Tue, 7 Mar 2023 14:24:31 -0800 (PST) Received: by mail-pl1-x62a.google.com with SMTP id ky4so15768407plb.3 for ; Tue, 07 Mar 2023 14:24:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227864; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=2fMO3DDvUJJeV0Q226fQtHUTjSXAJS4amcasCJTxOgo=; b=baut4pRknQmtSOiNrFOvRC5T+hL1Xi+k4T3XKC71MGFyHEwhwPJNwBWUF6p5EUkRkz NlY7R9ukJzhOrfBT9owOMnnrNCMWvNBxAEpK/4ofTKJFlVJf9kdt3K3YGL5RJOrK72p2 9dHefnfUiu8vkFS4oQGHXkVakK8c0pdzf6D5CHA8O0quBqA6tSj4Ed1Tdq16q4o529yw iPf6JS7sKO7SzXmVF8UoD0dwY3K5SJxf/3VSTgVOgvPEAdQdeqwbmOaSJKASyhEbI2/P SdiMSIYWlVyfikai3wcYH6Hz/SMyTOGt8tiADr+zWUI/ChDWLa03O6EGoNWXhOwqMU9K pcig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227864; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=2fMO3DDvUJJeV0Q226fQtHUTjSXAJS4amcasCJTxOgo=; b=dCgIKo5XbzlUA71Hpbc5QNEOeN7uGtXzNMV5PJoZnUuZZyWSfGhcIi9a0dB5/zBo9Q VXVARpqLt+9OVdcRwLKiE9J9/QUczj8D/yCtJqdyMPDTxhJP4Lj2uyPWQIfiCEz20xTj P9+25U6A9sPSgVngAvCcPY2eN2Z/44VnQuHlhU6bSx/DsulLHkQ5EkkfT/jmSo6AviGr pfTAeX2UhLwdl/Xm3cX7bQZgHFE5trdyo0aUocQULBtrq3O7cVTG29hq/FzwsjBfhJcS Hu7/znTKYO3zX6+s8+G4mmL4cbs32CMbfOXXoZPCtC56BIse6xT4CJEo0plA+BrJZHnW 0QYA== X-Gm-Message-State: AO0yUKVGLVY9J8fKLwmDWy4AIolEbk4ouZDkAQ5QBjWrDgNwHs0ukR1z BkxJ8WENoR4KfiQjd0q9PrtpJXI36PA= X-Google-Smtp-Source: AK7set9j79BlJ1H7xhvzqvNuittwP8TVj37nhEKqt9SDKwCzRF5NJST2f3KF3IAxMWCl3TiMunh3rw== X-Received: by 2002:a17:902:ab0c:b0:19b:c491:21be with SMTP id ik12-20020a170902ab0c00b0019bc49121bemr14787919plb.64.1678227864305; Tue, 07 Mar 2023 14:24:24 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:23 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 01/12] shared/crypto: Add bt_crypto_sirk Date: Tue, 7 Mar 2023 14:24:11 -0800 Message-Id: <20230307222422.2608483-1-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds bt_crypto_sirk which attempts to generate a unique SIRK using the following steps: - Generate a hash (k) using the str as input - Generate a hash (sirk) using vendor, product, version and source as input - Encrypt sirk using k as LTK with sef function. --- src/shared/crypto.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/shared/crypto.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/src/shared/crypto.c b/src/shared/crypto.c index 4cb2ea857ea8..5449621b55ea 100644 --- a/src/shared/crypto.c +++ b/src/shared/crypto.c @@ -926,3 +926,43 @@ bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16], return true; } + +/* Generates a SIRK from a string using the following steps: + * - Generate a hash (k) using the str as input + * - Generate a hash (sirk) using vendor, product, version and source as input + * - Encrypt sirk using k as LTK with sef function. + */ +bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor, + uint16_t product, uint16_t version, uint16_t source, + uint8_t sirk[16]) +{ + struct iovec iov[4]; + uint8_t k[16]; + uint8_t sirk_plaintext[16]; + + if (!crypto) + return false; + + iov[0].iov_base = (void *)str; + iov[0].iov_len = strlen(str); + + /* Generate a k using the str as input */ + if (!bt_crypto_gatt_hash(crypto, iov, 1, k)) + return false; + + iov[0].iov_base = &vendor; + iov[0].iov_len = sizeof(vendor); + iov[1].iov_base = &product; + iov[1].iov_len = sizeof(product); + iov[2].iov_base = &version; + iov[2].iov_len = sizeof(version); + iov[3].iov_base = &source; + iov[3].iov_len = sizeof(source); + + /* Generate a sirk using vendor, product, version and source as input */ + if (!bt_crypto_gatt_hash(crypto, iov, 4, sirk_plaintext)) + return false; + + /* Encrypt sirk using k as LTK with sef function */ + return bt_crypto_sef(crypto, k, sirk_plaintext, sirk); +} diff --git a/src/shared/crypto.h b/src/shared/crypto.h index fc1ba0c4feeb..d45308abf90a 100644 --- a/src/shared/crypto.h +++ b/src/shared/crypto.h @@ -57,3 +57,6 @@ bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16], const uint8_t sirk[16], uint8_t out[16]); bool bt_crypto_sih(struct bt_crypto *crypto, const uint8_t k[16], const uint8_t r[3], uint8_t hash[3]); +bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor, + uint16_t product, uint16_t version, uint16_t source, + uint8_t sirk[16]); From patchwork Tue Mar 7 22:24:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660710 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D7D4C6FD1E for ; Tue, 7 Mar 2023 22:25:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231213AbjCGWZZ (ORCPT ); Tue, 7 Mar 2023 17:25:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231734AbjCGWY7 (ORCPT ); Tue, 7 Mar 2023 17:24:59 -0500 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5AE0393E3A for ; Tue, 7 Mar 2023 14:24:31 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id y15-20020a17090aa40f00b00237ad8ee3a0so155192pjp.2 for ; Tue, 07 Mar 2023 14:24:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227865; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FhvXbrbfD2QqHIchqkMG4mmNdrbycE8pNBVZPDJ9Syc=; b=dIjwniVUyzj6EF5r1L2m8YX0787Sk63pWSkxnhtHIP/lCw7bR6OCq6y1tndqhuksml pRA8PcoqRZhp+eIMzzxh9pWuju1WkCu5Czr7/34/sL+hJj+S84ZjfHZ/b0szizor9Dij ZhYRbV5ylqXt5pzfVRdJJqniaNlggibTwsSP6xFkfvdpHeMc6Nbm+RvrV3gshKgUlqkG e2EjEzbh7am/WHV50JrMEQh+CU1FffS6LYe1htgupQgIu9Kxp6cseZHJ4oJPGCDQyFdG EdDEEP+m/nUrBOP/uq/Vn8udVpguOG90FOdIlvfettNLPb+/xXA2BHyNbAi8P1R3H3SN 8m3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227865; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FhvXbrbfD2QqHIchqkMG4mmNdrbycE8pNBVZPDJ9Syc=; b=hOR5xIj65RmdSE6jM6YVD6pQMQs7FS0FBjWOxo4LjaZtFkM5jtLV5qb1ggCeSChJZB lWDrXI74KaqJOCT9Y30rik/MaWUy2P8FOMo7EtPwgXfVg2MW0e8+OE3vg7le8Wki+sKs Tx8c/vkkAf+DmBlnGMa5Sqc/DJhNDDYYmt3D+IM3g9u4j67MuRB+BHdli+UPt1XiFBIC iRylNu7HiUUeMiZW6VfIMcqoSRwsvg02tQJTTacuhDXXthkPY1B1Xhi+NuC95kG7ohBl rS5ieisfKzlLh3UWhXREg9BJWOgwiadlNv2ZK1DRUqKyIVvrJbtxOarfwebnQsBmevsd uYCg== X-Gm-Message-State: AO0yUKV/rhFuNUG9QuftpuFvQQhfJ3Jyya3MmMrR0TnL5D14eAiApSgy WuJHHzyPJEWnaj2UjOADW40L2Nesk9M= X-Google-Smtp-Source: AK7set+7+PvaQXntd743PTv6jQBPjup75YV9K8WHowda29XTnL4NRuFNB2sX/bOcQ60P3ZhROQAw8w== X-Received: by 2002:a17:902:c10c:b0:19a:bbd0:c5ca with SMTP id 12-20020a170902c10c00b0019abbd0c5camr14792156pli.48.1678227865302; Tue, 07 Mar 2023 14:24:25 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:24 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 02/12] shared/ad: Add RSI data type Date: Tue, 7 Mar 2023 14:24:12 -0800 Message-Id: <20230307222422.2608483-2-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds BT_AD_CSIP_RSI advertising data type. --- src/shared/ad.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/ad.h b/src/shared/ad.h index feb712f508cf..b100a6796109 100644 --- a/src/shared/ad.h +++ b/src/shared/ad.h @@ -57,6 +57,7 @@ #define BT_AD_MESH_PROV 0x29 #define BT_AD_MESH_DATA 0x2a #define BT_AD_MESH_BEACON 0x2b +#define BT_AD_CSIP_RSI 0x2e #define BT_AD_3D_INFO_DATA 0x3d #define BT_AD_MANUFACTURER_DATA 0xff From patchwork Tue Mar 7 22:24:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660005 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18917C678D5 for ; Tue, 7 Mar 2023 22:25:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231320AbjCGWZ0 (ORCPT ); Tue, 7 Mar 2023 17:25:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231766AbjCGWZE (ORCPT ); Tue, 7 Mar 2023 17:25:04 -0500 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F40EE9662A for ; Tue, 7 Mar 2023 14:24:31 -0800 (PST) Received: by mail-pj1-x1030.google.com with SMTP id q31-20020a17090a17a200b0023750b69614so146408pja.5 for ; Tue, 07 Mar 2023 14:24:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227867; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=GMJPH4LKfsC1gbsemoIowAUoRkGzTRKYvd8HxwE27iI=; b=oVmz0OhGsIGBeMNscSZe+bnkuE7yuxo0GgC1uJRoIUf8nO6x+bF9TBmqlk1i2Ntkin aHdTn5c+6QbulVd+CQk9KPkGpYZeMewYZeOd34RByEJNDUo9Wj0kUKSYiAuC682eX2HV dK6dyEj+oCvwvpXqaEQbD6hqNoadCrsUrLaM1KtSi3PfLmDiof4kNVBIXbbNFb6qt/Dm zuy+QiVuaDtb9YVo9/udPATtQDsWaH5KDqVcYr7etosCJf33q8Tv+oYl9dWNha+sGB6q te6K/7RKYRCtk0m2gc0D3fQneQZQoUFGnEkOeiChadqvPgd8xUVvkUS5SUE8ZMgcMe/V 3xIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227867; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GMJPH4LKfsC1gbsemoIowAUoRkGzTRKYvd8HxwE27iI=; b=EXOdQ5lK3M5OeAgJDGtLThQjO9lC7vVO9nLFhoOcQeMZYGF21ZtkwLyn4G/G5qi5jJ M1NF/Mo3PuxRUzuOucPrCvUfrzomNpGcZqp2EbEw0na3+WTUHOYWerE3lfVoQJSTO4f0 pd954BDGYu0E0F+VUfRZbkFitK/BSg+hFkhGdFVfdu+5tq9cFy6acyrwp0QCpruHVvl4 pH8KxN/I1a99hlttjqoW9nuSlN3CmmPXwvrs3ZqxwwQzubMjITmVNrjqaWvJOBNxIpkc Wcav9B6Xdh0mm8M/NW5EmDrdzKjy9ppqf20UkxvKPRaWBgzo/xdLBRtYXQAkdWYZlApN id0Q== X-Gm-Message-State: AO0yUKWGr0TRyue2Dhud9h7d3o1jzk1dI2KDIRCiAb2V5s/1Fq0seJC5 DXzxfN226bLP7oRPvrw0O2l75AhfzjE= X-Google-Smtp-Source: AK7set8Fcpc1PWnax/xBF0IqR1FsKpkyWyy6uO5zYtzG/mvfqo4dU8NydZGyap6tu8wEWd4vU4NaEA== X-Received: by 2002:a17:902:9b84:b0:19e:7d66:ff29 with SMTP id y4-20020a1709029b8400b0019e7d66ff29mr13250691plp.61.1678227866912; Tue, 07 Mar 2023 14:24:26 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:26 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 03/12] doc: Add set-api Date: Tue, 7 Mar 2023 14:24:13 -0800 Message-Id: <20230307222422.2608483-3-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds set-api.rst which documents DeviceSet interface. --- doc/set-api.rst | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 doc/set-api.rst diff --git a/doc/set-api.rst b/doc/set-api.rst new file mode 100644 index 000000000000..c49be1ae0514 --- /dev/null +++ b/doc/set-api.rst @@ -0,0 +1,53 @@ +===================================== +BlueZ D-Bus DeviceSet API description +===================================== + + +DeviceSet interface +=================== + +Service org.bluez +Interface org.bluez.DeviceSet1 +Object path [variable prefix]/{hci0,hci1,...}/set_{sirk} + +Methods +======= + +**void Connect() [experimental]** + + Connects all **devices** members of the set, each member is + connected in sequence as they were added/loaded following the + same proceedure as described in **Device1.Connect**. + + Possible errors: org.bluez.Error.NotReady + org.bluez.Error.Failed + org.bluez.Error.InProgress + org.bluez.Error.AlreadyConnected + +**void Disconnect() [experimental]** + + Disconnects all **devices** members of the set, each member is + disconnected in sequence as they were connected following the + same proceedure as described in **Device1.Disconnect**. + + Possible errors: org.bluez.Error.NotConnected + +Properties +========== + +**object Adapter [readonly]** + + The object path of the adapter the set belongs to. + +**bool AutoConnect [read-write, experimental]** + + Indicates if the **devices** members of the set shall be automatically + connected once any of its members is connected. + +**array(object) Devices [ready-only, experimental]** + + List of devices objects that are members of the set. + +**byte Size [read-only, experimental]** + + Set members size. From patchwork Tue Mar 7 22:24:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660709 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E02DC6FD1E for ; Tue, 7 Mar 2023 22:25:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231453AbjCGWZ2 (ORCPT ); Tue, 7 Mar 2023 17:25:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231782AbjCGWZJ (ORCPT ); Tue, 7 Mar 2023 17:25:09 -0500 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BF8E96603 for ; Tue, 7 Mar 2023 14:24:37 -0800 (PST) Received: by mail-pj1-x1033.google.com with SMTP id m8-20020a17090a4d8800b002377bced051so251130pjh.0 for ; Tue, 07 Mar 2023 14:24:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227868; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=tYyQX+0EeYSzuu9TE8HE0kzl55hbyMad+FvqeBkBoGw=; b=pUUsAISzCtO5/2EELpsd0yxFt2nDnEzA5udrrV79QAbcpvilmvaYEYoCdIYQW/d9zs gFSL1YIl6eFqN/8nq9kbExF6opAV64sNug5oPRqWqayXmLf/u58aLPwr3G7hYWeEYYAI fkTCD7pFaUq2whZalz18fMrgYIqsfphfs14zV2qi4TsU6g/dywM58wvYRKJREUOmlI56 XfDYlEGWQ4TFjktCbuxJF+VTAlseWP1BdnhrkYgASiK1vzqwOKB9u3qfaVC4fLQMS1hP eIPVbz3uwMkydZ7wBhIMNrkPRJwhenxqQC1AJ8hYMvGsNZaujO0e2rkWWXogVutozIUN WbAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227868; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tYyQX+0EeYSzuu9TE8HE0kzl55hbyMad+FvqeBkBoGw=; b=I+KVlSD1rMKMF5jUR9Ifd8MfjWeLVw/z43AnwqAa650klU2+jWPxTiszj7kJPKOh5x 6M4LCBl0EKuhkG9mgvHOuCJb1NDQdz5AqJL0ry+0FLHqh/bVctNQ56KvEuNEH3dhmtUg YecaJzoh4gCoZ+ix92ZjELezuAnSs07Ozju6mg5rBd6Xr8uVedzFcHD6pOPn0uoLmwUZ mOjHtMQjJps1M1a/LZhVqA/so5rbyCKaMsBn7Gvoi79V7v74rE5jzYwhcw2uQMt6M250 pVGpc2lTHWi/Bg7NZpCVZTzWVmro1poku0SjCGxvbl/wXq5fEDg5MUcUn2x5LZovmnGv c24g== X-Gm-Message-State: AO0yUKWVxrMDynLDRg58IDcA6zDqJ4GRT7kJwBQLGJ2kOqrhtYqRYiPV jeift9BUW268QCnMJmPpt667WX1AQgA= X-Google-Smtp-Source: AK7set8euEc4jQ4QskJkpyVCz6Sq+AKquYtw8zbnHNhxIuYJjZwNnjbNN9Upkkzvw6HvFGDPUvtUFw== X-Received: by 2002:a17:903:40c4:b0:19d:74c:78e5 with SMTP id t4-20020a17090340c400b0019d074c78e5mr15311201pld.50.1678227868012; Tue, 07 Mar 2023 14:24:28 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.27 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:27 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 04/12] device-api: Add Set property Date: Tue, 7 Mar 2023 14:24:14 -0800 Message-Id: <20230307222422.2608483-4-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds Set property so clients are able to identify when a device belongs to a set. --- doc/device-api.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/device-api.txt b/doc/device-api.txt index 628accb8a572..e4a8d3c5af33 100644 --- a/doc/device-api.txt +++ b/doc/device-api.txt @@ -281,3 +281,13 @@ Properties string Address [readonly] Example: 0x26 0x01 0x01... + + array{object, dict} Sets [readonly, experimental] + + The object paths of the sets the device belongs to + followed by a dictionary which can contain the + following: + + byte Rank: + + Rank of the device in the Set. From patchwork Tue Mar 7 22:24:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660004 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E01FC678D5 for ; Tue, 7 Mar 2023 22:25:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229849AbjCGWZi (ORCPT ); Tue, 7 Mar 2023 17:25:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230210AbjCGWZU (ORCPT ); Tue, 7 Mar 2023 17:25:20 -0500 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4966B47430 for ; Tue, 7 Mar 2023 14:24:51 -0800 (PST) Received: by mail-pj1-x1030.google.com with SMTP id h11-20020a17090a2ecb00b00237c740335cso152164pjs.3 for ; Tue, 07 Mar 2023 14:24:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227870; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=HDk89JeAshy+PSg7OOFte0Xd+S6Ux3KmprwIlkATpDI=; b=FBwqFhAHFgR6wsWvuAnhBGycF8D5kNbK5X7OP4HbXFDLlC9qlWYsKicNLiWWkdQvkD CL7XA99eldEteBWgJ49F0rgdh/1B49ZZlGVvd3Pp62qkHszrx5JduNttYE4V74j50VX7 GW4olBtDj/kKhzYq2n9bBQ+daYWJDCylkbuZ0EzdsvbANBXDJWCvNMQYEYTzUqyF9/TV aKPqehs3BVZgs3ph80CbTsV3FkWfirWC9aHSoUC44E163NzlaOMWG84V2V/cBgFO+iux BT5a7WQ0x5CUCrznAVq5B+JA+PmRhRroyIpb5SgNk3BXrZAwvZFUccOzZOCecgzQ+ec4 nfWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227870; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HDk89JeAshy+PSg7OOFte0Xd+S6Ux3KmprwIlkATpDI=; b=cvCck61Shiz8F/XIeevxed1CA2nL284pvkyDKwzZ0feHmOl75HOfZyBgNN2KVyQGNz DS3b7vyrPpcGN10XuQDT/5O4rURlDF322806cDQNyMTUfqpxydlrriTBr6EBwSyHuwnI 0u7kNhp49XYic2p2I7zHteaTx8GcBLkmeI54bjmbBjoYRXnObfnVbgsTV6Ka5a+K7VXB i2aD5C5NVAGEYhKN5V0pJIbJwO2QpVQJFbUGWOgZbzQxW3tD7j6mk8FqEYtfbIDSJ3MF vLHRCqZk1P/3IZ0N/ZVIOgOLLnID8XqDv/DfcCL1zMYeoS8oJbhmN+vfaksu6qgMKiAl cZMQ== X-Gm-Message-State: AO0yUKVFhTp/lNCVdDTPrZVNO9wtLIq8cF+OyJOSxvw0UyFCcxrFMwdY /9gS9O4dPWny3IZG+eF2do+wJyqrQz4= X-Google-Smtp-Source: AK7set8NbU3ZXqm3WmI/XcUScqs6e8SFEk+MDCdN0bHRM+AG4Wn94xio7z6yi/R7SdfHCGyxeZgA8A== X-Received: by 2002:a17:902:dac3:b0:19a:a6ec:6721 with SMTP id q3-20020a170902dac300b0019aa6ec6721mr19997524plx.16.1678227869502; Tue, 07 Mar 2023 14:24:29 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:28 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 05/12] core: Add initial implementation of DeviceSet interface Date: Tue, 7 Mar 2023 14:24:15 -0800 Message-Id: <20230307222422.2608483-5-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds the initial implementation of DeviceSet interface as documented in doc/set-api.rst. --- Makefile.am | 3 +- src/adapter.c | 6 +- src/device.c | 283 +++++++++++++++++++++++++++++++++++++- src/device.h | 11 +- src/set.c | 371 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/set.h | 20 +++ 6 files changed, 683 insertions(+), 11 deletions(-) create mode 100644 src/set.c create mode 100644 src/set.h diff --git a/Makefile.am b/Makefile.am index 0e8cce249c7d..7b010c8159e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -326,7 +326,8 @@ src_bluetoothd_SOURCES = $(builtin_sources) \ src/eir.h src/eir.c \ src/adv_monitor.h src/adv_monitor.c \ src/battery.h src/battery.c \ - src/settings.h src/settings.c + src/settings.h src/settings.c \ + src/set.h src/set.c src_bluetoothd_LDADD = lib/libbluetooth-internal.la \ gdbus/libgdbus-internal.la \ src/libshared-glib.la \ diff --git a/src/adapter.c b/src/adapter.c index 538310c1ddc6..ae0eb364bad5 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -4387,8 +4387,8 @@ static void load_ltks(struct btd_adapter *adapter, GSList *keys) if (dev) { device_set_paired(dev, info->bdaddr_type); device_set_bonded(dev, info->bdaddr_type); - device_set_ltk_enc_size(dev, info->enc_size); - device_set_ltk_enc_size(dev, info->enc_size); + device_set_ltk(dev, info->val, info->central, + info->enc_size); } } @@ -8657,7 +8657,7 @@ 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); + device_set_ltk(device, ev->key.val, ev->key.central, ev->key.enc_size); bonding_complete(adapter, &addr->bdaddr, addr->type, 0); } diff --git a/src/device.c b/src/device.c index cb16d37c1ae1..df50ce7b4f6c 100644 --- a/src/device.c +++ b/src/device.c @@ -64,6 +64,7 @@ #include "storage.h" #include "eir.h" #include "settings.h" +#include "set.h" #define DISCONNECT_TIMER 2 #define DISCOVERY_TIMER 1 @@ -159,11 +160,25 @@ struct bearer_state { time_t last_seen; }; +struct ltk_info { + uint8_t key[16]; + bool central; + uint8_t enc_size; +}; + struct csrk_info { uint8_t key[16]; uint32_t counter; }; +struct sirk_info { + struct btd_device_set *set; + uint8_t encrypted; + uint8_t key[16]; + uint8_t size; + uint8_t rank; +}; + enum { WAKE_FLAG_DEFAULT = 0, WAKE_FLAG_ENABLED, @@ -253,7 +268,8 @@ struct btd_device { struct csrk_info *local_csrk; struct csrk_info *remote_csrk; - uint8_t ltk_enc_size; + struct ltk_info *ltk; + struct queue *sirks; sdp_list_t *tmp_records; @@ -386,6 +402,24 @@ static void store_csrk(struct csrk_info *csrk, GKeyFile *key_file, g_key_file_set_integer(key_file, group, "Counter", csrk->counter); } +static void store_sirk(struct sirk_info *sirk, GKeyFile *key_file, + uint8_t index) +{ + char group[28]; + char key[33]; + int i; + + sprintf(group, "SetIdentityResolvingKey#%u", index); + + for (i = 0; i < 16; i++) + sprintf(key + (i * 2), "%2.2X", sirk->key[i]); + + g_key_file_set_boolean(key_file, group, "Encrypted", sirk->encrypted); + g_key_file_set_string(key_file, group, "Key", key); + g_key_file_set_integer(key_file, group, "Size", sirk->size); + g_key_file_set_integer(key_file, group, "Rank", sirk->rank); +} + static gboolean store_device_info_cb(gpointer user_data) { struct btd_device *device = user_data; @@ -483,6 +517,18 @@ static gboolean store_device_info_cb(gpointer user_data) if (device->remote_csrk) store_csrk(device->remote_csrk, key_file, "RemoteSignatureKey"); + if (!queue_isempty(device->sirks)) { + const struct queue_entry *entry; + int i; + + for (entry = queue_get_entries(device->sirks), i = 0; entry; + entry = entry->next, i++) { + struct sirk_info *sirk = entry->data; + + store_sirk(sirk, key_file, i); + } + } + str = g_key_file_to_data(key_file, &length, NULL); if (!g_file_set_contents(filename, str, length, &gerr)) { error("Unable set contents for %s: (%s)", filename, @@ -804,8 +850,11 @@ static void device_free(gpointer user_data) if (device->eir_uuids) g_slist_free_full(device->eir_uuids, g_free); + queue_destroy(device->sirks, free); + g_free(device->local_csrk); g_free(device->remote_csrk); + free(device->ltk); g_free(device->path); g_free(device->alias); free(device->modalias); @@ -1607,6 +1656,62 @@ static gboolean dev_property_wake_allowed_exist( return device_get_wake_support(device); } +static void append_set(void *data, void *user_data) +{ + struct sirk_info *info = data; + const char *path = btd_set_get_path(info->set); + DBusMessageIter *iter = user_data; + DBusMessageIter entry, dict; + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, + &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &path); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + g_dbus_dict_append_entry(&dict, "Rank", DBUS_TYPE_BYTE, &info->rank); + + dbus_message_iter_close_container(&entry, &dict); + dbus_message_iter_close_container(iter, &entry); +} + +static gboolean dev_property_get_set(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device *device = data; + DBusMessageIter array; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_OBJECT_PATH_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + + queue_foreach(device->sirks, append_set, &array); + + dbus_message_iter_close_container(iter, &array); + + return TRUE; +} + +static gboolean dev_property_set_exists(const GDBusPropertyTable *property, + void *data) +{ + struct btd_device *device = data; + + return !queue_isempty(device->sirks); +} + static bool disconnect_all(gpointer user_data) { struct btd_device *device = user_data; @@ -1792,10 +1897,97 @@ 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) +static void add_set(void *data, void *user_data) { - device->ltk_enc_size = enc_size; - bt_att_set_enc_key_size(device->att, device->ltk_enc_size); + struct sirk_info *sirk = data; + struct btd_device *device = user_data; + struct btd_device_set *set; + + if (!sirk->encrypted) + return; + + set = btd_set_add_device(device, device->ltk->key, sirk->key, + sirk->size); + if (!set) + return; + + if (sirk->set != set) { + sirk->set = set; + g_dbus_emit_property_changed(dbus_conn, device->path, + DEVICE_INTERFACE, "Sets"); + } +} + +void device_set_ltk(struct btd_device *device, const uint8_t val[16], + bool central, uint8_t enc_size) +{ + if (!device->ltk) + device->ltk = new0(struct ltk_info, 1); + + memcpy(device->ltk->key, val, sizeof(device->ltk->key)); + device->ltk->central = central; + device->ltk->enc_size = enc_size; + bt_att_set_enc_key_size(device->att, enc_size); + + /* Check if there is any set/sirk that needs decryption */ + queue_foreach(device->sirks, add_set, device); +} + +static bool match_sirk(const void *data, const void *match_data) +{ + const struct sirk_info *sirk = data; + const uint8_t *key = match_data; + + return !memcmp(sirk->key, key, sizeof(sirk->key)); +} + +static struct sirk_info *device_add_sirk_info(struct btd_device *device, + bool encrypted, uint8_t key[16], + uint8_t size, uint8_t rank) +{ + struct sirk_info *sirk; + + sirk = queue_find(device->sirks, match_sirk, key); + if (sirk) + return sirk; + + sirk = new0(struct sirk_info, 1); + sirk->encrypted = encrypted; + memcpy(sirk->key, key, sizeof(sirk->key)); + sirk->size = size; + sirk->rank = rank; + + queue_push_tail(device->sirks, sirk); + store_device_info(device); + + return sirk; +} + +bool btd_device_add_set(struct btd_device *device, bool encrypted, + uint8_t key[16], uint8_t size, uint8_t rank) +{ + struct btd_device_set *set; + struct sirk_info *sirk; + + if (encrypted && !device->ltk) + return false; + + sirk = device_add_sirk_info(device, encrypted, key, size, rank); + if (!sirk) + return false; + + set = btd_set_add_device(device, encrypted ? device->ltk->key : NULL, + key, size); + if (!set) + return false; + + if (sirk->set != set) { + sirk->set = set; + g_dbus_emit_property_changed(dbus_conn, device->path, + DEVICE_INTERFACE, "Sets"); + } + + return true; } static void device_set_auto_connect(struct btd_device *device, gboolean enable) @@ -2996,6 +3188,8 @@ static const GDBusPropertyTable device_properties[] = { { "WakeAllowed", "b", dev_property_get_wake_allowed, dev_property_set_wake_allowed, dev_property_wake_allowed_exist }, + { "Sets", "a{oa{sv}}", dev_property_get_set, NULL, + dev_property_set_exists }, { } }; @@ -3290,6 +3484,63 @@ fail: return NULL; } +static struct sirk_info *load_sirk(GKeyFile *key_file, uint8_t index) +{ + char group[28]; + struct sirk_info *sirk; + char *str; + int i; + + sprintf(group, "SetIdentityResolvingKey#%u", index); + + str = g_key_file_get_string(key_file, group, "Key", NULL); + if (!str) + return NULL; + + sirk = g_new0(struct sirk_info, 1); + + for (i = 0; i < 16; i++) { + if (sscanf(str + (i * 2), "%2hhx", &sirk->key[i]) != 1) + goto fail; + } + + + sirk->encrypted = g_key_file_get_boolean(key_file, group, "Encrypted", + NULL); + sirk->size = g_key_file_get_integer(key_file, group, "Size", NULL); + sirk->rank = g_key_file_get_integer(key_file, group, "Rank", NULL); + g_free(str); + + return sirk; + +fail: + g_free(str); + g_free(sirk); + return NULL; +} + +static void load_sirks(struct btd_device *device, GKeyFile *key_file) +{ + struct sirk_info *sirk; + uint8_t i; + + for (i = 0; i < UINT8_MAX; i++) { + sirk = load_sirk(key_file, i); + if (!sirk) + break; + + queue_push_tail(device->sirks, sirk); + + /* Only add DeviceSet object if sirk does need + * decryption otherwise it has to wait for the LTK in + * order to decrypt. + */ + if (!sirk->encrypted) + btd_set_add_device(device, NULL, sirk->key, + sirk->size); + } +} + static void load_services(struct btd_device *device, char **uuids) { char **uuid; @@ -3430,6 +3681,8 @@ static void load_info(struct btd_device *device, const char *local, device->local_csrk = load_csrk(key_file, "LocalSignatureKey"); device->remote_csrk = load_csrk(key_file, "RemoteSignatureKey"); + + load_sirks(device, key_file); } g_strfreev(techno); @@ -3945,6 +4198,7 @@ static struct btd_device *device_new(struct btd_adapter *adapter, } device->adapter = adapter; + device->sirks = queue_new(); device->temporary = true; device->db_id = gatt_db_register(device->db, gatt_service_added, @@ -5207,7 +5461,9 @@ static void gatt_server_init(struct btd_device *device, return; } - bt_att_set_enc_key_size(device->att, device->ltk_enc_size); + if (device->ltk) + bt_att_set_enc_key_size(device->att, device->ltk->enc_size); + bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL); btd_gatt_database_server_connected(database, device->server); @@ -6760,6 +7016,14 @@ struct btd_device *btd_device_ref(struct btd_device *device) return device; } +static void remove_sirk_info(void *data, void *user_data) +{ + struct sirk_info *info = data; + struct btd_device *device = user_data; + + btd_set_remove_device(info->set, device); +} + void btd_device_unref(struct btd_device *device) { if (__sync_sub_and_fetch(&device->ref_count, 1)) @@ -6770,6 +7034,9 @@ void btd_device_unref(struct btd_device *device) return; } + if (!queue_isempty(device->sirks)) + queue_foreach(device->sirks, remove_sirk_info, device); + DBG("Freeing device %s", device->path); g_dbus_unregister_interface(dbus_conn, device->path, DEVICE_INTERFACE); @@ -6928,3 +7195,9 @@ int8_t btd_device_get_volume(struct btd_device *device) { return device->volume; } + +void btd_device_foreach_ad(struct btd_device *dev, bt_ad_func_t func, + void *data) +{ + bt_ad_foreach_data(dev->ad, func, data); +} diff --git a/src/device.h b/src/device.h index 9e81fda9e948..96347ff229cc 100644 --- a/src/device.h +++ b/src/device.h @@ -128,8 +128,10 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type, bool *remove); 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); - +void device_set_ltk(struct btd_device *device, const uint8_t val[16], + bool central, uint8_t enc_size); +bool btd_device_add_set(struct btd_device *device, bool encrypted, + uint8_t sirk[16], uint8_t size, uint8_t rank); void device_store_svc_chng_ccc(struct btd_device *device, uint8_t bdaddr_type, uint16_t value); void device_load_svc_chng_ccc(struct btd_device *device, uint16_t *ccc_le, @@ -188,3 +190,8 @@ void btd_device_cleanup(void); void btd_device_set_volume(struct btd_device *dev, int8_t volume); int8_t btd_device_get_volume(struct btd_device *dev); + +typedef void (*bt_device_ad_func_t)(void *data, void *user_data); + +void btd_device_foreach_ad(struct btd_device *dev, bt_device_ad_func_t func, + void *data); diff --git a/src/set.c b/src/set.c new file mode 100644 index 000000000000..5836a06b887a --- /dev/null +++ b/src/set.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2023 Intel Corporation + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gdbus/gdbus.h" +#include "src/shared/util.h" +#include "src/shared/queue.h" +#include "src/shared/ad.h" +#include "src/shared/crypto.h" + +#include "log.h" +#include "error.h" +#include "adapter.h" +#include "device.h" +#include "dbus-common.h" +#include "set.h" + +static struct queue *set_list; + +struct btd_device_set { + struct btd_adapter *adapter; + char *path; + uint8_t sirk[16]; + uint8_t size; + bool auto_connect; + struct queue *devices; + struct btd_device *device; +}; + +static DBusMessage *set_disconnect(DBusConnection *conn, DBusMessage *msg, + void *user_data) +{ + /* TODO */ + return NULL; +} + +static DBusMessage *set_connect(DBusConnection *conn, DBusMessage *msg, + void *user_data) +{ + /* TODO */ + return NULL; +} + +static const GDBusMethodTable set_methods[] = { + { GDBUS_EXPERIMENTAL_ASYNC_METHOD("Disconnect", NULL, NULL, + set_disconnect) }, + { GDBUS_EXPERIMENTAL_ASYNC_METHOD("Connect", NULL, NULL, + set_connect) }, + {} +}; + +static gboolean get_adapter(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device_set *set = data; + const char *path = adapter_get_path(set->adapter); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); + + return TRUE; +} + +static gboolean get_auto_connect(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device_set *set = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, + &set->auto_connect); + + return TRUE; +} + +static void set_auto_connect(const GDBusPropertyTable *property, + DBusMessageIter *iter, + GDBusPendingPropertySet id, void *data) +{ + struct btd_device_set *set = data; + dbus_bool_t b; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) { + g_dbus_pending_property_error(id, + ERROR_INTERFACE ".InvalidArguments", + "Invalid arguments in method call"); + return; + } + + dbus_message_iter_get_basic(iter, &b); + + set->auto_connect = b ? true : false; + + g_dbus_pending_property_success(id); +} + +static void append_device(void *data, void *user_data) +{ + struct btd_device *device = data; + const char *path = device_get_path(device); + DBusMessageIter *entry = user_data; + + dbus_message_iter_append_basic(entry, DBUS_TYPE_OBJECT_PATH, &path); +} + +static gboolean get_devices(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device_set *set = data; + DBusMessageIter entry; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_OBJECT_PATH_AS_STRING, + &entry); + + queue_foreach(set->devices, append_device, &entry); + + dbus_message_iter_close_container(iter, &entry); + + return TRUE; +} + +static gboolean get_size(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct btd_device_set *set = data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &set->size); + + return TRUE; +} + +static const GDBusPropertyTable set_properties[] = { + { "Adapter", "o", get_adapter, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "AutoConnect", "b", get_auto_connect, set_auto_connect, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "Devices", "ao", get_devices, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "Size", "y", get_size, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + {} +}; + +static void set_free(void *data) +{ + struct btd_device_set *set = data; + + queue_destroy(set->devices, NULL); + g_free(set->path); + free(set); +} + +static struct btd_device_set *set_new(struct btd_device *device, + uint8_t sirk[16], uint8_t size) +{ + struct btd_device_set *set; + + set = new0(struct btd_device_set, 1); + set->adapter = device_get_adapter(device); + memcpy(set->sirk, sirk, sizeof(set->sirk)); + set->size = size; + set->auto_connect = true; + set->devices = queue_new(); + queue_push_tail(set->devices, device); + set->path = g_strdup_printf("%s/set_%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x", + adapter_get_path(set->adapter), + sirk[15], sirk[14], sirk[13], sirk[12], + sirk[11], sirk[10], sirk[9], sirk[8], + sirk[7], sirk[6], sirk[5], sirk[4], + sirk[3], sirk[2], sirk[1], sirk[0]); + + DBG("Creating set %s", set->path); + + if (g_dbus_register_interface(btd_get_dbus_connection(), + set->path, BTD_DEVICE_SET_INTERFACE, + set_methods, NULL, + set_properties, set, + set_free) == FALSE) { + error("Unable to register set interface"); + set_free(set); + return NULL; + } + + return set; +} + +static struct btd_device_set *set_find(struct btd_device *device, + uint8_t sirk[16]) +{ + struct btd_adapter *adapter = device_get_adapter(device); + const struct queue_entry *entry; + + for (entry = queue_get_entries(set_list); entry; entry = entry->next) { + struct btd_device_set *set = entry->data; + + if (set->adapter != adapter) + continue; + + if (!memcmp(set->sirk, sirk, sizeof(set->sirk))) + return set; + } + + return NULL; +} + +static void set_connect_next(struct btd_device_set *set) +{ + const struct queue_entry *entry; + + for (entry = queue_get_entries(set->devices); entry; + entry = entry->next) { + struct btd_device *device = entry->data; + + /* Only connect one at time(?) */ + if (!device_connect_le(device)) + return; + } +} + +static void set_add(struct btd_device_set *set, struct btd_device *device) +{ + /* Check if device is already part of the set then skip to connect */ + if (queue_find(set->devices, NULL, device)) + goto done; + + DBG("set %s device %s", set->path, device_get_path(device)); + + queue_push_tail(set->devices, device); + g_dbus_emit_property_changed(btd_get_dbus_connection(), set->path, + BTD_DEVICE_SET_INTERFACE, "Devices"); + +done: + /* Check if set is marked to auto-connect */ + if (btd_device_is_connected(device) && set->auto_connect) + set_connect_next(set); +} + +static void foreach_rsi(void *data, void *user_data) +{ + struct bt_ad_data *ad = data; + struct btd_device_set *set = user_data; + struct bt_crypto *crypto; + uint8_t res[3]; + + if (ad->type != BT_AD_CSIP_RSI || ad->len < 6) + return; + + crypto = bt_crypto_new(); + if (!crypto) + return; + + if (!bt_crypto_sih(crypto, set->sirk, ad->data + 3, res)) { + bt_crypto_unref(crypto); + return; + } + + bt_crypto_unref(crypto); + + if (!memcmp(ad->data, res, sizeof(res))) { + btd_device_set_temporary(set->device, false); + device_connect_le(set->device); + } +} + +static void foreach_device(struct btd_device *device, void *data) +{ + struct btd_device_set *set = data; + + /* Check if device is already part of the set then skip */ + if (queue_find(set->devices, NULL, device)) + return; + + set->device = device; + + btd_device_foreach_ad(device, foreach_rsi, set); +} + +struct btd_device_set *btd_set_add_device(struct btd_device *device, + uint8_t *key, uint8_t sirk[16], + uint8_t size) +{ + struct btd_device_set *set; + + /* In case key has been set it means SIRK is encrypted */ + if (key) { + struct bt_crypto *crypto = bt_crypto_new(); + + if (!crypto) + return NULL; + + /* sef and sdf are symmetric */ + bt_crypto_sef(crypto, key, sirk, sirk); + + bt_crypto_unref(crypto); + } + + /* Check if DeviceSet already exists */ + set = set_find(device, sirk); + if (set) { + set_add(set, device); + return set; + } + + set = set_new(device, sirk, size); + if (!set) + return NULL; + + if (!set_list) + set_list = queue_new(); + + queue_push_tail(set_list, set); + + /* Attempt to add devices which have matching RSI */ + btd_adapter_for_each_device(device_get_adapter(device), foreach_device, + set); + + return set; +} + +bool btd_set_remove_device(struct btd_device_set *set, + struct btd_device *device) +{ + if (!set || !device) + return false; + + if (!queue_remove_if(set->devices, NULL, device)) + return false; + + if (!queue_isempty(set->devices)) { + g_dbus_emit_property_changed(btd_get_dbus_connection(), + set->path, + BTD_DEVICE_SET_INTERFACE, + "Devices"); + return true; + } + + if (!queue_remove(set_list, set)) + return false; + + /* Unregister if there are no devices left in the set */ + g_dbus_unregister_interface(btd_get_dbus_connection(), set->path, + BTD_DEVICE_SET_INTERFACE); + + return true; +} + +const char *btd_set_get_path(struct btd_device_set *set) +{ + return set->path; +} diff --git a/src/set.h b/src/set.h new file mode 100644 index 000000000000..67177e8c7946 --- /dev/null +++ b/src/set.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2023 Intel Corporation + * + * + */ + +#define BTD_DEVICE_SET_INTERFACE "org.bluez.DeviceSet1" + +struct btd_device_set; + +struct btd_device_set *btd_set_add_device(struct btd_device *device, + uint8_t *ltk, uint8_t sirk[16], + uint8_t size); +bool btd_set_remove_device(struct btd_device_set *set, + struct btd_device *device); +const char *btd_set_get_path(struct btd_device_set *set); From patchwork Tue Mar 7 22:24:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660708 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0F58C6FA99 for ; Tue, 7 Mar 2023 22:25:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229720AbjCGWZk (ORCPT ); Tue, 7 Mar 2023 17:25:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230350AbjCGWZW (ORCPT ); Tue, 7 Mar 2023 17:25:22 -0500 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27F1AAF74A for ; Tue, 7 Mar 2023 14:24:54 -0800 (PST) Received: by mail-pl1-x62d.google.com with SMTP id i10so15734075plr.9 for ; Tue, 07 Mar 2023 14:24:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227871; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=eQ7sv22ULGj99ITd+yshAiGuwxfr6k3MEwP/5i6IzAg=; b=kQrLZ/lQp9Md+q0W9iS3hfKu6Q4lA2g4cGWrlOda9Y73iKAfND6yPtQst1dQU8BKYQ os4vREv70Sg3cqsdoCivGb/INR7Ux0kziyUh+v5OdjPFq3ZLEcwwSpEh0Zpi/djSUeiq 894yEjbMUpaqIDeDeTFcQ4ksZ6UI7fci+xm1Bh2g2yeXhBFQtAjmxcOtsM66BU65m2M7 R8g4w9E/u568Zb668oHI9jFlpf9OndFoplJNA4XSYMK2HH12lmz8L/EZtYD8jscx/27G ZJZM5AFkBY7syDcXnVZ74Y3/PFj/V4PKi5klcke2AhjWFTqPbfhxc9fGep/JJ0BvVOVV aPjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227871; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eQ7sv22ULGj99ITd+yshAiGuwxfr6k3MEwP/5i6IzAg=; b=r8voeF1frogeMM2JuqqtDuavhwULA0UxcsK+er5SHkJKZE4qGduPQ7eaT+OEVw5u3k N9JFH9XV4RkAG8yeb48rolHNLJdKGE0GHivZWE9jwtzD/QyZsmsKoavcutNaRmkLim5l /oVGhSghZRyd3AlINFLaiLfYxGWt9BmJWqgq9NRQsDkQ414DcItn8hmpl+k3ZBOyWJLY 1HCg5BqyzYZJAbvXN/xmYhEEekyiwqDgiiQCQejW+5Ndc4ZtTCmdTm9YqVbsrdtIhGeo WksgcOmYkchUD2ue8KpZDqKeuXj49W5sNBcfJZwITvWY/YY/IAvgC+029NX00bIFlkrm 4FJA== X-Gm-Message-State: AO0yUKXzVqkrxpjrxGFMyD2jV7CaHcJwotBHb7A0gkSrGjiLXzsECIxj 7XhFmtZmOf56mzbCik9HEGoyJrHA0g8= X-Google-Smtp-Source: AK7set92i1SkvM35OSRTEE5k0T9e+j52ROfTY0BGdznq+IqEenCjmSNdBIMQ9Qv8nCsgkMpS5qYfWQ== X-Received: by 2002:a17:902:ebc4:b0:19d:461:9628 with SMTP id p4-20020a170902ebc400b0019d04619628mr18142252plg.34.1678227871131; Tue, 07 Mar 2023 14:24:31 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:30 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 06/12] core: Check if device has RSI Date: Tue, 7 Mar 2023 14:24:16 -0800 Message-Id: <20230307222422.2608483-6-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This checks if device is advertising an RSI and if so disregards if it is not discoverable since other members can be. --- src/adapter.c | 4 ++-- src/eir.c | 3 +++ src/eir.h | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index ae0eb364bad5..7947160a6c5c 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -7122,7 +7122,7 @@ void btd_adapter_update_found_device(struct btd_adapter *adapter, dev = btd_adapter_find_device(adapter, bdaddr, bdaddr_type); if (!dev) { - if (!discoverable && !monitoring) { + if (!discoverable && !monitoring && !eir_data.rsi) { eir_data_free(&eir_data); return; } @@ -7169,7 +7169,7 @@ void btd_adapter_update_found_device(struct btd_adapter *adapter, /* If there is no matched Adv monitors, don't continue if not * discoverable or if active discovery filter don't match. */ - if (!monitoring && (!discoverable || + if (!eir_data.rsi && !monitoring && (!discoverable || (adapter->filtered_discovery && !is_filter_match( adapter->discovery_list, &eir_data, rssi)))) { eir_data_free(&eir_data); diff --git a/src/eir.c b/src/eir.c index 2f9ee036ffd5..52152c0d7f52 100644 --- a/src/eir.c +++ b/src/eir.c @@ -236,6 +236,9 @@ static void eir_parse_data(struct eir_data *eir, uint8_t type, memcpy(ad->data, data, len); eir->data_list = g_slist_append(eir->data_list, ad); + + if (type == EIR_CSIP_RSI) + eir->rsi = true; } void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len) diff --git a/src/eir.h b/src/eir.h index 6154e23ec266..a4bf5fbd33f3 100644 --- a/src/eir.h +++ b/src/eir.h @@ -37,6 +37,7 @@ #define EIR_SVC_DATA32 0x20 /* LE: Service data, 32-bit UUID */ #define EIR_SVC_DATA128 0x21 /* LE: Service data, 128-bit UUID */ #define EIR_TRANSPORT_DISCOVERY 0x26 /* Transport Discovery Service */ +#define EIR_CSIP_RSI 0x2e /* Resolvable Set Identifier */ #define EIR_MANUFACTURER_DATA 0xFF /* Manufacturer Specific Data */ /* Flags Descriptions */ @@ -76,6 +77,7 @@ struct eir_data { uint32_t class; uint16_t appearance; bool name_complete; + bool rsi; int8_t tx_power; uint8_t *hash; uint8_t *randomizer; From patchwork Tue Mar 7 22:24:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660003 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B7C42C678D5 for ; Tue, 7 Mar 2023 22:25:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229540AbjCGWZ6 (ORCPT ); Tue, 7 Mar 2023 17:25:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53094 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231521AbjCGWZc (ORCPT ); Tue, 7 Mar 2023 17:25:32 -0500 Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 985F3B04AD for ; Tue, 7 Mar 2023 14:25:02 -0800 (PST) Received: by mail-pl1-x629.google.com with SMTP id u5so15729351plq.7 for ; Tue, 07 Mar 2023 14:25:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227873; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=DgTfiZrjPFHYXsaM8eCTZSSY0mCirVfYD1ClAxwO8NA=; b=Gl87ZwJ9XS5+si/96yj3+eZ9gXzNbehbdA4nydHqBaqdCltlGL6h9sfQeMi1GOCctt FfKfFAP+ilr+RvENNefel+Pv1h172/C61AEaenmaiulGxn7uFG6Jh6lP50pxzBeUeLiQ qB8SiDd8eA/0BIUPgAXvL/tO13nxMhzRmvoi9joLOAuFm0CqpaKe9GyHpSh9bGgjyxPN bor77uYcY5QIZ/eDd1GQrsIoDdx7/ocBEIKGf1z4/+QH4lXRyC9p1IRFI0oTBAS25Zw+ R2aCpFqoVKE/mzf1t7kMUdEFZmPPqBVQ5PGhWbv9jOAcrPO9Na0/CCNS6BRy6gjmlVul 39ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227873; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DgTfiZrjPFHYXsaM8eCTZSSY0mCirVfYD1ClAxwO8NA=; b=jqKymkTDHrhi2ddu1xGkxiXq2K612rGrmkLfoApkYXgvrwHefVg/Z/JI/cYguO7qny lg/OOeIwDdQDXIiFBXpry3BRcB0CCGHe/Cxkb9U5rybkyfIdjfNaKfevGntQ78p+ho55 qMpBI4H5mNlYcpnj9P58hTdLvgU3Uwm8JbZfJs4cqGsz6f/TdmUCP7C/draUc36dO90C v1Hbu5B/Ro9BhaimOX+ZLZc8aO817trjN/0nv67gcIAZo/AYjJiMKUXIPcdt3xdKEtYw rz/kjqfzy7JavwTwietl9Q5NYyFGclKvTGkFXDFebVow9O8a7rf9P2Yy73/OV33kEzey V6dA== X-Gm-Message-State: AO0yUKUw4yb6MH6tro2joEfmIvFvknf7IE7J1Ddf+XdFXnOpUukg7NFf NL9bYsg6yDtvIjdV04Z7n7ZwYQ6jiEk= X-Google-Smtp-Source: AK7set8/baXS7W1SVnd/AKGFpA8XAy7B5Tfc638eMwJFI9uYI5cwX9QkcTnKgOWqqV5PsONyxU7aVw== X-Received: by 2002:a17:903:2446:b0:19c:d78b:cdc with SMTP id l6-20020a170903244600b0019cd78b0cdcmr21881565pls.5.1678227872521; Tue, 07 Mar 2023 14:24:32 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.31 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:31 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 07/12] main.conf: Add CSIP profile configurable options Date: Tue, 7 Mar 2023 14:24:17 -0800 Message-Id: <20230307222422.2608483-7-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sathish Narasimman This introduces option to configure main.conf that can be used to configure co-ordinated set identification profile. --- src/btd.h | 9 ++++ src/main.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.conf | 25 ++++++++++ 3 files changed, 158 insertions(+) diff --git a/src/btd.h b/src/btd.h index 42cffcde43ca..70051c71c7c1 100644 --- a/src/btd.h +++ b/src/btd.h @@ -92,6 +92,13 @@ struct btd_defaults { struct btd_le_defaults le; }; +struct btd_csis { + bool encrypt; + uint8_t sirk[16]; + uint8_t size; + uint8_t rank; +}; + struct btd_avdtp_opts { uint8_t session_mode; uint8_t stream_mode; @@ -142,6 +149,8 @@ struct btd_opts { enum jw_repairing_t jw_repairing; struct btd_advmon_opts advmon; + + struct btd_csis csis; }; extern struct btd_opts btd_opts; diff --git a/src/main.c b/src/main.c index 99d9c508ff91..2a4d9be05d7a 100644 --- a/src/main.c +++ b/src/main.c @@ -43,6 +43,7 @@ #include "shared/mainloop.h" #include "shared/timeout.h" #include "shared/queue.h" +#include "shared/crypto.h" #include "lib/uuid.h" #include "shared/util.h" #include "btd.h" @@ -60,6 +61,9 @@ #define DEFAULT_TEMPORARY_TIMEOUT 30 /* 30 seconds */ #define DEFAULT_NAME_REQUEST_RETRY_DELAY 300 /* 5 minutes */ +/*CSIP Profile - Server */ +#define DEFAULT_SIRK "761FAE703ED681F0C50B34155B6434FB" + #define SHUTDOWN_GRACE_SECONDS 10 struct btd_opts btd_opts; @@ -146,6 +150,13 @@ static const char *gatt_options[] = { NULL }; +static const char *csip_options[] = { + "SIRK", + "Size", + "Rank", + NULL +}; + static const char *avdtp_options[] = { "SessionMode", "StreamMode", @@ -166,11 +177,55 @@ static const struct group_table { { "LE", le_options }, { "Policy", policy_options }, { "GATT", gatt_options }, + { "CSIP", csip_options }, { "AVDTP", avdtp_options }, { "AdvMon", advmon_options }, { } }; +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +static int8_t check_sirk_alpha_numeric(char *str) +{ + int8_t val = 0; + char *s = str; + + if (strlen(s) != 32) /* 32 Bytes of Alpha numeric string */ + return 0; + + for ( ; *s; s++) { + if (((*s >= '0') & (*s <= '9')) + || ((*s >= 'a') && (*s <= 'z')) + || ((*s >= 'A') && (*s <= 'Z'))) { + val = 1; + } else { + val = 0; + break; + } + } + + return val; +} + +static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) +{ + size_t i, len; + + if (!hexstr) + return 0; + + len = MIN((strlen(hexstr) / 2), buflen); + memset(buf, 0, len); + + for (i = 0; i < len; i++) { + if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1) + continue; + } + + return len; +} GKeyFile *btd_get_main_conf(void) { @@ -652,6 +707,27 @@ static void btd_parse_kernel_experimental(char **list) } } +static bool gen_sirk(const char *str) +{ + struct bt_crypto *crypto; + int ret; + + crypto = bt_crypto_new(); + if (!crypto) { + error("Failed to open crypto"); + return false; + } + + ret = bt_crypto_sirk(crypto, str, btd_opts.did_vendor, + btd_opts.did_product, btd_opts.did_version, + btd_opts.did_source, btd_opts.csis.sirk); + if (!ret) + error("Failed to generate SIRK"); + + bt_crypto_unref(crypto); + return ret; +} + static void parse_config(GKeyFile *config) { GError *err = NULL; @@ -939,6 +1015,54 @@ static void parse_config(GKeyFile *config) btd_opts.gatt_channels = val; } + str = g_key_file_get_string(config, "CSIP", "SIRK", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + DBG("CSIS SIRK: %s", str); + + if (strlen(str) == 32 && check_sirk_alpha_numeric(str)) { + hex2bin(str, btd_opts.csis.sirk, + sizeof(btd_opts.csis.sirk)); + } else if (!gen_sirk(str)) + DBG("Unable to generate SIRK from string"); + + g_free(str); + } + + boolean = g_key_file_get_boolean(config, "CSIP", "SIRK", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + DBG("CSIS Encryption: %s", boolean ? "true" : "false"); + + btd_opts.csis.encrypt = boolean; + } + + val = g_key_file_get_integer(config, "CSIP", "Size", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + val = MIN(val, 0xFF); + val = MAX(val, 0); + DBG("CSIS Size: %u", val); + btd_opts.csis.size = val; + } + + val = g_key_file_get_integer(config, "CSIP", "Rank", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + val = MIN(val, 0xFF); + val = MAX(val, 0); + DBG("CSIS Rank: %u", val); + btd_opts.csis.rank = val; + } + str = g_key_file_get_string(config, "AVDTP", "SessionMode", &err); if (err) { DBG("%s", err->message); diff --git a/src/main.conf b/src/main.conf index f187c9aaa482..11172c9dd7c6 100644 --- a/src/main.conf +++ b/src/main.conf @@ -258,6 +258,31 @@ # Default to 3 #Channels = 3 +[CSIS] +# SIRK - Set Identification Resolution Key which is common for all the +# sets. They SIRK key is used to identify its sets. This can be any +# 128 bit value or a string value (e.g. product name) which is then hashed. +# Possible Values: +# 16 byte hexadecimal value: 861FAE703ED681F0C50B34155B6434FB +# String value: "My Product Name" +# Defaults to none +#SIRK = + +# SIRK Encryption +# Possible values: +# yes: Encrypt SIRK when read +# no: Do not encrypt SIRK when read. (plaintext) +# Defaults to yes +#Encryption = yes + +# Total no of sets belongs to this Profile +# Defaults to 0 +#Size = 0 + +# Rank for the device +# Defaults to 0 +#Rank = 0 + [AVDTP] # AVDTP L2CAP Signalling Channel Mode. # Possible values: From patchwork Tue Mar 7 22:24:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660707 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54E62C6FA99 for ; Tue, 7 Mar 2023 22:26:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229876AbjCGW0D (ORCPT ); Tue, 7 Mar 2023 17:26:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230054AbjCGWZl (ORCPT ); Tue, 7 Mar 2023 17:25:41 -0500 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BFFFBB04BD for ; Tue, 7 Mar 2023 14:25:06 -0800 (PST) Received: by mail-pl1-x636.google.com with SMTP id i5so15771265pla.2 for ; Tue, 07 Mar 2023 14:25:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227874; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=86eFv5lJLkAIs8HuA53ZU2TbeiSwcGz4TepJdxj4T70=; b=QaynkUbX3BJLwoNw2SxyGFurS6/C9fHvpD9fSm4y9BUStXkLIh9mGwUiAFF/IVb20a vWM5rxwvlzn1uvQNVBNRVMN/yeramcztrNaBQJZOtmLD4IutQ/KTSNGEp2HxxTttBTFV pL9nNg1Wqo1xcJ3K6MlP68fWwkYC0r/HlgTS0LOTC8EDliymaW9w0nmqUWb5BizhlfyK z3iW80kd13f/AqIDFfa8/pvl9UKQO3LWJrYcoI3aCXfGOKVZ1g57A4tm8iu5tpFY6uyS mllprh50ZXAamBDrWZRmTHKKq74y7QXl2gzChXi1iNvFo5lpGKHJj1gL17DBofvhlOgy xTig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227874; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=86eFv5lJLkAIs8HuA53ZU2TbeiSwcGz4TepJdxj4T70=; b=ZPH5dKLZl/BvtbuzXrt1u4Z+IgrtFsqgFR7mh/GDYmhtlHH+98WzXEJR6xGbj+5qo0 hCOhgqa8QjCQyCA1olYq7HI1wNoiGPMdy3tA4+Yeuxi8jPG3HH/RpSTZPLo7b/wcjmiY mYeb2mSFk2VPIEHz7hUg2Oriu4SBtpRAKJNqmCFhhr7n6PfdoodNbskwNamvS2SlrFcC B8nMlfCVP+RtGR+VsprtfeLMjSSbiFTP6zZBvFmqm3l1wOO0ruoWVdO4zaYc0IrOPFIp 8D+9PiyAUuBTmc+YZ9Z40ZaEsGNLJY14ZkWCEgPB2JZOgoY9pkOA/B4ieWsIs67km2Bs cI6Q== X-Gm-Message-State: AO0yUKV2qz/ShliguQIOTA/QLHg+uwjnRx3nS6I+haLwG7DLy5M5PYFe K1XHsy+rQkF/MNYwlNX5khD31nRMeL4= X-Google-Smtp-Source: AK7set+tSWJ8WMUUy4l4yaKXjrj3ns5ccRT4ikt28aZcMj+5W13Rimz3i49QYuFKcwZCwfFaX+StKA== X-Received: by 2002:a17:903:451:b0:19e:73f6:9f3f with SMTP id iw17-20020a170903045100b0019e73f69f3fmr15033571plb.57.1678227873781; Tue, 07 Mar 2023 14:24:33 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:33 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 08/12] shared/csip: Add initial code for handling CSIP Date: Tue, 7 Mar 2023 14:24:18 -0800 Message-Id: <20230307222422.2608483-8-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sathish Narasimman This adds initial code for Coordinated Set Identification Profile. --- Makefile.am | 1 + src/shared/csip.c | 866 ++++++++++++++++++++++++++++++++++++++++++++++ src/shared/csip.h | 67 ++++ 3 files changed, 934 insertions(+) create mode 100644 src/shared/csip.c create mode 100644 src/shared/csip.h diff --git a/Makefile.am b/Makefile.am index 7b010c8159e9..7ded3ba75138 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \ src/shared/bap.h src/shared/bap.c src/shared/ascs.h \ src/shared/mcs.h src/shared/mcp.h src/shared/mcp.c \ src/shared/vcp.c src/shared/vcp.h \ + src/shared/csip.c src/shared/csip.h \ src/shared/lc3.h src/shared/tty.h if READLINE diff --git a/src/shared/csip.c b/src/shared/csip.c new file mode 100644 index 000000000000..ff2047a4ade0 --- /dev/null +++ b/src/shared/csip.c @@ -0,0 +1,866 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include + +#include "lib/bluetooth.h" +#include "lib/uuid.h" + +#include "src/shared/queue.h" +#include "src/shared/util.h" +#include "src/shared/timeout.h" +#include "src/shared/att.h" +#include "src/shared/gatt-db.h" +#include "src/shared/gatt-server.h" +#include "src/shared/gatt-client.h" +#include "src/shared/crypto.h" +#include "src/shared/csip.h" + +#define DBG(_csip, fmt, arg...) \ + csip_debug(_csip, "%s:%s() " fmt, __FILE__, __func__, ## arg) + +/* SIRK is now hardcoded in the code. This can be moved + * to a configuration file. Since the code is to validate + * the CSIP use case of set member + */ +#define SIRK "761FAE703ED681F0C50B34155B6434FB" +#define CSIS_SIZE 0x02 +#define CSIS_LOCK 0x01 +#define CSIS_RANK 0x01 +#define CSIS_PLAINTEXT 0x01 +#define CSIS_ENC 0x02 + +struct bt_csip_db { + struct gatt_db *db; + struct bt_csis *csis; +}; + +struct csis_sirk { + uint8_t type; + uint8_t val[16]; +} __packed; + +struct bt_csis { + struct bt_csip_db *cdb; + struct csis_sirk *sirk_val; + uint8_t size_val; + uint8_t lock_val; + uint8_t rank_val; + struct gatt_db_attribute *service; + struct gatt_db_attribute *sirk; + struct gatt_db_attribute *size; + struct gatt_db_attribute *lock; + struct gatt_db_attribute *lock_ccc; + struct gatt_db_attribute *rank; +}; + +struct bt_csip_cb { + unsigned int id; + bt_csip_func_t attached; + bt_csip_func_t detached; + void *user_data; +}; + +struct bt_csip_ready { + unsigned int id; + bt_csip_ready_func_t func; + bt_csip_destroy_func_t destroy; + void *data; +}; + +struct bt_csip { + int ref_count; + struct bt_csip_db *ldb; + struct bt_csip_db *rdb; + struct bt_gatt_client *client; + struct bt_att *att; + + unsigned int idle_id; + struct queue *ready_cbs; + + bt_csip_debug_func_t debug_func; + bt_csip_destroy_func_t debug_destroy; + void *debug_data; + + bt_csip_ltk_func_t ltk_func; + void *ltk_data; + + bt_csip_sirk_func_t sirk_func; + void *sirk_data; + + void *user_data; +}; + +static struct queue *csip_db; +static struct queue *csip_cbs; +static struct queue *sessions; + +static void csip_detached(void *data, void *user_data) +{ + struct bt_csip_cb *cb = data; + struct bt_csip *csip = user_data; + + cb->detached(csip, cb->user_data); +} + +void bt_csip_detach(struct bt_csip *csip) +{ + if (!queue_remove(sessions, csip)) + return; + + bt_gatt_client_unref(csip->client); + csip->client = NULL; + + queue_foreach(csip_cbs, csip_detached, csip); +} + +static void csip_db_free(void *data) +{ + struct bt_csip_db *cdb = data; + + if (!cdb) + return; + + gatt_db_unref(cdb->db); + + free(cdb->csis); + free(cdb); +} + +static void csip_ready_free(void *data) +{ + struct bt_csip_ready *ready = data; + + if (ready->destroy) + ready->destroy(ready->data); + + free(ready); +} + +static void csip_free(void *data) +{ + struct bt_csip *csip = data; + + bt_csip_detach(csip); + + csip_db_free(csip->rdb); + + queue_destroy(csip->ready_cbs, csip_ready_free); + + free(csip); +} + +struct bt_att *bt_csip_get_att(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + if (csip->att) + return csip->att; + + return bt_gatt_client_get_att(csip->client); +} + +struct bt_csip *bt_csip_ref(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + __sync_fetch_and_add(&csip->ref_count, 1); + + return csip; +} + +static struct bt_csip *bt_csip_ref_safe(struct bt_csip *csip) +{ + if (!csip || !csip->ref_count) + return NULL; + + return bt_csip_ref(csip); +} + +void bt_csip_unref(struct bt_csip *csip) +{ + if (!csip) + return; + + if (__sync_sub_and_fetch(&csip->ref_count, 1)) + return; + + csip_free(csip); +} + +static void csip_debug(struct bt_csip *csip, const char *format, ...) +{ + va_list ap; + + if (!csip || !format || !csip->debug_func) + return; + + va_start(ap, format); + util_debug_va(csip->debug_func, csip->debug_data, format, ap); + va_end(ap); +} + +static bool csip_match_att(const void *data, const void *match_data) +{ + const struct bt_csip *csip = data; + const struct bt_att *att = match_data; + + return bt_csip_get_att((void *)csip) == att; +} + +static bool csis_sirk_enc(struct bt_csis *csis, struct bt_att *att, + struct csis_sirk *sirk) +{ + struct bt_csip *csip; + uint8_t k[16]; + struct bt_crypto *crypto; + bool ret; + + csip = queue_find(sessions, csip_match_att, att); + if (!csip) + return false; + + if (!csip->ltk_func(csip, k, csip->ltk_data)) { + DBG(csip, "Unable to read sef key"); + return false; + } + + crypto = bt_crypto_new(); + if (!crypto) { + DBG(csip, "Failed to open crypto"); + return false; + } + + ret = bt_crypto_sef(crypto, k, sirk->val, sirk->val); + if (!ret) + DBG(csip, "Failed to encrypt SIRK using sef"); + + bt_crypto_unref(crypto); + + return ret; +} + +static void csis_sirk_read(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + struct bt_csis *csis = user_data; + struct csis_sirk sirk; + struct iovec iov; + + memcpy(&sirk, csis->sirk_val, sizeof(sirk)); + + if (sirk.type == BT_CSIP_SIRK_ENCRYPT && + !csis_sirk_enc(csis, att, &sirk)) { + gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY, + NULL, 0); + return; + } + + iov.iov_base = &sirk; + iov.iov_len = sizeof(sirk); + + gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, + iov.iov_len); +} + +static void csis_size_read(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + struct bt_csis *csis = user_data; + struct iovec iov; + + iov.iov_base = &csis->size; + iov.iov_len = sizeof(csis->size); + + gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, + iov.iov_len); +} + +static void csis_lock_read_cb(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + uint8_t value = CSIS_LOCK; + + gatt_db_attribute_read_result(attrib, id, 0, &value, sizeof(value)); +} + +static void csis_lock_write_cb(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + const uint8_t *value, size_t len, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + gatt_db_attribute_write_result(attrib, id, 0); +} + +static void csis_rank_read_cb(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + uint8_t value = CSIS_RANK; + + gatt_db_attribute_read_result(attrib, id, 0, &value, sizeof(value)); +} + +static struct bt_csis *csis_new(struct gatt_db *db) +{ + struct bt_csis *csis; + + if (!db) + return NULL; + + csis = new0(struct bt_csis, 1); + + return csis; +} + +static struct bt_csip_db *csip_db_new(struct gatt_db *db) +{ + struct bt_csip_db *cdb; + + if (!db) + return NULL; + + cdb = new0(struct bt_csip_db, 1); + cdb->db = gatt_db_ref(db); + + if (!csip_db) + csip_db = queue_new(); + + cdb->csis = csis_new(db); + cdb->csis->cdb = cdb; + + queue_push_tail(csip_db, cdb); + + return cdb; +} + +bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data) +{ + if (!csip) + return false; + + csip->user_data = user_data; + + return true; +} + +static bool csip_db_match(const void *data, const void *match_data) +{ + const struct bt_csip_db *cdb = data; + const struct gatt_db *db = match_data; + + return (cdb->db == db); +} + +static struct bt_csip_db *csip_get_db(struct gatt_db *db) +{ + struct bt_csip_db *cdb; + + cdb = queue_find(csip_db, csip_db_match, db); + if (cdb) + return cdb; + + return csip_db_new(db); +} + +void bt_csip_add_db(struct gatt_db *db) +{ + csip_db_new(db); +} + +bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func, + void *user_data, bt_csip_destroy_func_t destroy) +{ + if (!csip) + return false; + + if (csip->debug_destroy) + csip->debug_destroy(csip->debug_data); + + csip->debug_func = func; + csip->debug_destroy = destroy; + csip->debug_data = user_data; + + return true; +} + +unsigned int bt_csip_register(bt_csip_func_t attached, bt_csip_func_t detached, + void *user_data) +{ + struct bt_csip_cb *cb; + static unsigned int id; + + if (!attached && !detached) + return 0; + + if (!csip_cbs) + csip_cbs = queue_new(); + + cb = new0(struct bt_csip_cb, 1); + cb->id = ++id ? id : ++id; + cb->attached = attached; + cb->detached = detached; + cb->user_data = user_data; + + queue_push_tail(csip_cbs, cb); + + return cb->id; +} + +static bool match_id(const void *data, const void *match_data) +{ + const struct bt_csip_cb *cb = data; + unsigned int id = PTR_TO_UINT(match_data); + + return (cb->id == id); +} + +bool bt_csip_unregister(unsigned int id) +{ + struct bt_csip_cb *cb; + + cb = queue_remove_if(csip_cbs, match_id, UINT_TO_PTR(id)); + if (!cb) + return false; + + free(cb); + + return true; +} + +struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb) +{ + struct bt_csip *csip; + struct bt_csip_db *db; + + if (!ldb) + return NULL; + + db = csip_get_db(ldb); + if (!db) + return NULL; + + csip = new0(struct bt_csip, 1); + csip->ldb = db; + csip->ready_cbs = queue_new(); + + if (!rdb) + goto done; + + db = new0(struct bt_csip_db, 1); + db->db = gatt_db_ref(rdb); + + csip->rdb = db; + +done: + bt_csip_ref(csip); + + return csip; +} + +static struct bt_csis *csip_get_csis(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + if (csip->rdb->csis) + return csip->rdb->csis; + + csip->rdb->csis = new0(struct bt_csis, 1); + csip->rdb->csis->cdb = csip->rdb; + + return csip->rdb->csis; +} + +static void read_sirk(bool success, uint8_t att_ecode, const uint8_t *value, + uint16_t length, void *user_data) +{ + struct bt_csip *csip = user_data; + struct bt_csis *csis; + struct csis_sirk *sirk; + struct iovec iov = { + .iov_base = (void *)value, + .iov_len = length + }; + + if (!success) { + DBG(csip, "Unable to read SIRK: error 0x%02x", att_ecode); + return; + } + + csis = csip_get_csis(csip); + if (!csis) + return; + + sirk = util_iov_pull_mem(&iov, sizeof(*sirk)); + if (!sirk) { + DBG(csip, "Invalid size for SIRK: len %u", length); + return; + } + + if (!csis->sirk_val) + csis->sirk_val = new0(struct csis_sirk, 1); + + memcpy(csis->sirk_val, sirk, sizeof(*sirk)); +} + +static void read_size(bool success, uint8_t att_ecode, const uint8_t *value, + uint16_t length, void *user_data) +{ + struct bt_csip *csip = user_data; + struct bt_csis *csis; + + if (!success) { + DBG(csip, "Unable to read Size: error 0x%02x", att_ecode); + return; + } + + csis = csip_get_csis(csip); + if (!csis) + return; + + csis->size_val = *value; +} + +static void read_rank(bool success, uint8_t att_ecode, const uint8_t *value, + uint16_t length, void *user_data) +{ + struct bt_csip *csip = user_data; + struct bt_csis *csis; + + if (!success) { + DBG(csip, "Unable to read Rank: error 0x%02x", att_ecode); + return; + } + + csis = csip_get_csis(csip); + if (!csis) + return; + + csis->rank_val = *value; +} + +static void csip_notify_ready(struct bt_csip *csip) +{ + const struct queue_entry *entry; + + if (!bt_csip_ref_safe(csip)) + return; + + for (entry = queue_get_entries(csip->ready_cbs); entry; + entry = entry->next) { + struct bt_csip_ready *ready = entry->data; + + ready->func(csip, ready->data); + } + + bt_csip_unref(csip); +} + +static void foreach_csis_char(struct gatt_db_attribute *attr, void *user_data) +{ + struct bt_csip *csip = user_data; + uint16_t value_handle; + bt_uuid_t uuid, uuid_sirk, uuid_size, uuid_rank; + struct bt_csis *csis; + + if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, + NULL, NULL, &uuid)) + return; + + bt_uuid16_create(&uuid_sirk, CS_SIRK); + bt_uuid16_create(&uuid_size, CS_SIZE); + bt_uuid16_create(&uuid_rank, CS_RANK); + + if (!bt_uuid_cmp(&uuid, &uuid_sirk)) { + DBG(csip, "SIRK found: handle 0x%04x", value_handle); + + csis = csip_get_csis(csip); + if (!csis || csis->sirk) + return; + + csis->sirk = attr; + + bt_gatt_client_read_value(csip->client, value_handle, read_sirk, + csip, NULL); + + return; + } + + if (!bt_uuid_cmp(&uuid, &uuid_size)) { + DBG(csip, "Size found: handle 0x%04x", value_handle); + + csis = csip_get_csis(csip); + if (!csis) + return; + + csis->size = attr; + + bt_gatt_client_read_value(csip->client, value_handle, read_size, + csip, NULL); + } + + if (!bt_uuid_cmp(&uuid, &uuid_rank)) { + DBG(csip, "Rank found: handle 0x%04x", value_handle); + + csis = csip_get_csis(csip); + if (!csis) + return; + + csis->rank = attr; + + bt_gatt_client_read_value(csip->client, value_handle, read_rank, + csip, NULL); + } +} +static void foreach_csis_service(struct gatt_db_attribute *attr, + void *user_data) +{ + struct bt_csip *csip = user_data; + struct bt_csis *csis = csip_get_csis(csip); + + csis->service = attr; + + gatt_db_service_set_claimed(attr, true); + + gatt_db_service_foreach_char(attr, foreach_csis_char, csip); +} + +static void csip_idle(void *data) +{ + struct bt_csip *csip = data; + + csip->idle_id = 0; + + csip_notify_ready(csip); +} + +bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client) +{ + bt_uuid_t uuid; + + if (!sessions) + sessions = queue_new(); + + queue_push_tail(sessions, csip); + + if (!client) + return true; + + if (csip->client) + return false; + + csip->client = bt_gatt_client_clone(client); + if (!csip->client) + return false; + + csip->idle_id = bt_gatt_client_idle_register(csip->client, csip_idle, + csip, NULL); + + bt_uuid16_create(&uuid, CSIS_UUID); + gatt_db_foreach_service(csip->rdb->db, &uuid, foreach_csis_service, + csip); + + return true; +} + +static struct csis_sirk *sirk_new(struct bt_csis *csis, struct gatt_db *db, + uint8_t type, uint8_t k[16], + uint8_t size, uint8_t rank) +{ + struct csis_sirk *sirk; + bt_uuid_t uuid; + struct gatt_db_attribute *cas; + + if (!csis) + return NULL; + + if (csis->sirk) + sirk = csis->sirk_val; + else + sirk = new0(struct csis_sirk, 1); + + sirk->type = type; + memcpy(sirk->val, k, sizeof(sirk->val)); + csis->sirk_val = sirk; + csis->size_val = size; + csis->lock_val = 1; + csis->rank_val = rank; + + /* Check if service already active as that means the attributes have + * already been registered. + */ + if (gatt_db_service_get_active(csis->service)) + return sirk; + + /* Populate DB with CSIS attributes */ + bt_uuid16_create(&uuid, CSIS_UUID); + csis->service = gatt_db_add_service(db, &uuid, true, 10); + + bt_uuid16_create(&uuid, CS_SIRK); + csis->sirk = gatt_db_service_add_characteristic(csis->service, + &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_sirk_read, NULL, + csis); + + bt_uuid16_create(&uuid, CS_SIZE); + csis->size = gatt_db_service_add_characteristic(csis->service, + &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_size_read, NULL, + csis); + + /* Lock */ + bt_uuid16_create(&uuid, CS_LOCK); + csis->lock = gatt_db_service_add_characteristic(csis->service, &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ | + BT_GATT_CHRC_PROP_WRITE | + BT_GATT_CHRC_PROP_NOTIFY, + csis_lock_read_cb, + csis_lock_write_cb, + csis); + + csis->lock_ccc = gatt_db_service_add_ccc(csis->service, + BT_ATT_PERM_READ | BT_ATT_PERM_WRITE); + + /* Rank */ + bt_uuid16_create(&uuid, CS_RANK); + csis->rank = gatt_db_service_add_characteristic(csis->service, &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_rank_read_cb, + NULL, csis); + + /* Add the CAS service */ + bt_uuid16_create(&uuid, 0x1853); + cas = gatt_db_add_service(db, &uuid, true, 2); + gatt_db_service_add_included(cas, csis->service); + gatt_db_service_set_active(cas, true); + gatt_db_service_add_included(cas, csis->service); + + gatt_db_service_set_active(csis->service, true); + + return sirk; +} + +bool bt_csip_set_sirk(struct bt_csip *csip, bool encrypt, + uint8_t k[16], uint8_t size, uint8_t rank, + bt_csip_ltk_func_t func, void *user_data) +{ + uint8_t zero[16] = {}; + uint8_t type; + + if (!csip || !csip->ldb || !memcmp(k, zero, sizeof(zero))) + return false; + + type = encrypt ? BT_CSIP_SIRK_ENCRYPT : BT_CSIP_SIRK_CLEARTEXT; + + /* In case of encrypted type requires sef key function */ + if (type == BT_CSIP_SIRK_ENCRYPT && !func) + return false; + + if (!sirk_new(csip->ldb->csis, csip->ldb->db, type, k, size, rank)) + return false; + + csip->ltk_func = func; + csip->ltk_data = user_data; + + return true; +} + +bool bt_csip_get_sirk(struct bt_csip *csip, uint8_t *type, + uint8_t k[16], uint8_t *size, uint8_t *rank) +{ + struct bt_csis *csis; + + if (!csip) + return false; + + csis = csip_get_csis(csip); + if (!csis) + return false; + + if (type) + *type = csis->sirk_val->type; + + memcpy(k, csis->sirk_val->val, sizeof(csis->sirk_val->val)); + + if (size) + *size = csis->size_val; + + if (rank) + *rank = csis->rank_val; + + return true; +} + +unsigned int bt_csip_ready_register(struct bt_csip *csip, + bt_csip_ready_func_t func, void *user_data, + bt_csip_destroy_func_t destroy) +{ + struct bt_csip_ready *ready; + static unsigned int id; + + if (!csip) + return 0; + + ready = new0(struct bt_csip_ready, 1); + ready->id = ++id ? id : ++id; + ready->func = func; + ready->destroy = destroy; + ready->data = user_data; + + queue_push_tail(csip->ready_cbs, ready); + + return ready->id; +} + +static bool match_ready_id(const void *data, const void *match_data) +{ + const struct bt_csip_ready *ready = data; + unsigned int id = PTR_TO_UINT(match_data); + + return (ready->id == id); +} + +bool bt_csip_ready_unregister(struct bt_csip *csip, unsigned int id) +{ + struct bt_csip_ready *ready; + + ready = queue_remove_if(csip->ready_cbs, match_ready_id, + UINT_TO_PTR(id)); + if (!ready) + return false; + + csip_ready_free(ready); + + return true; +} diff --git a/src/shared/csip.h b/src/shared/csip.h new file mode 100644 index 000000000000..0f8acb1cae82 --- /dev/null +++ b/src/shared/csip.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + */ + +#include +#include + +#include "src/shared/io.h" + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +struct bt_csip; + +enum { + BT_CSIP_SIRK_ENCRYPT = 0x00, + BT_CSIP_SIRK_CLEARTEXT = 0x01 +}; + +typedef void (*bt_csip_ready_func_t)(struct bt_csip *csip, void *user_data); +typedef void (*bt_csip_destroy_func_t)(void *user_data); +typedef void (*bt_csip_debug_func_t)(const char *str, void *user_data); +typedef void (*bt_csip_func_t)(struct bt_csip *csip, void *user_data); +typedef bool (*bt_csip_ltk_func_t)(struct bt_csip *csip, uint8_t k[16], + void *user_data); +typedef bool (*bt_csip_sirk_func_t)(struct bt_csip *csip, uint8_t type, + uint8_t k[16], uint8_t size, uint8_t rank, + void *user_data); + +struct bt_csip *bt_csip_ref(struct bt_csip *csip); +void bt_csip_unref(struct bt_csip *csip); + +void bt_csip_add_db(struct gatt_db *db); + +bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client); +void bt_csip_detach(struct bt_csip *csip); + +bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func, + void *user_data, bt_csip_destroy_func_t destroy); + +struct bt_att *bt_csip_get_att(struct bt_csip *csip); + +bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data); + +/* Session related function */ +unsigned int bt_csip_register(bt_csip_func_t added, bt_csip_func_t removed, + void *user_data); +bool bt_csip_unregister(unsigned int id); +struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb); + +bool bt_csip_set_sirk(struct bt_csip *csip, bool encrypt, + uint8_t k[16], uint8_t size, uint8_t rank, + bt_csip_ltk_func_t func, void *user_data); + +bool bt_csip_get_sirk(struct bt_csip *csip, uint8_t *type, + uint8_t k[16], uint8_t *size, uint8_t *rank); + +unsigned int bt_csip_ready_register(struct bt_csip *csip, + bt_csip_ready_func_t func, void *user_data, + bt_csip_destroy_func_t destroy); +bool bt_csip_ready_unregister(struct bt_csip *csip, unsigned int id); From patchwork Tue Mar 7 22:24:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660002 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48EA3C6FD1E for ; Tue, 7 Mar 2023 22:26:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230054AbjCGW0E (ORCPT ); Tue, 7 Mar 2023 17:26:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52658 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230098AbjCGWZm (ORCPT ); Tue, 7 Mar 2023 17:25:42 -0500 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35191B06C4 for ; Tue, 7 Mar 2023 14:25:07 -0800 (PST) Received: by mail-pl1-x62f.google.com with SMTP id a9so15716220plh.11 for ; Tue, 07 Mar 2023 14:25:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227875; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=QkQOloDQBql5f4S+4NOFgI3qikHTXcOuf3pdWCcDAMs=; b=LAW8ZI5ETLCtqyE5LJLFcmPS+wOy+qxBxn64zpSp6wJUU2H+DgNt33/LudPGe6ZKZ0 jfQRPicFrprheZ1gDys5DoCktndIpLhsPpUBKE6DOCTLUrYRub4avrJH/CTXUnNcR3WQ gGYl0MtAiumuff5X6GhFre7Ihba5IHOAPRjL/IF0VNLkCDg8lGOF0EGUPNuctFyMWbTA zqmoaoa2oVc1nC8NvLWOyhcgqwD6waK+v9DjD6NmJSV4rmS4jTAQIozxnY9iulWBacPM SKi+LooDkhN5V9p1wQYcDz7esz5Z/2RT0roBTyTiANwwKmtRonSh3Bb6oJkVaUZth40s CxTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227875; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QkQOloDQBql5f4S+4NOFgI3qikHTXcOuf3pdWCcDAMs=; b=VUVJ+FCBIdASbTo5dyKLr96RVOzYN4Uiu962WImO8S+2uvkRmu+EKp+3rr8175DkDC DDbvUr2NQkMFfD6yiwkjJdMYsk1SzB1lYWDctmIbz+mhEQBIUKgN3yX5TV9fWsNQDCa3 enqyG7q6AcIYxVDT6EbQXItacZV4r4B1A3VNPz0wAGNiMRMiLshY5eZs16L1BULyQYny DjmA89WXnYAtOcvf2pA9GWwDnqOYaoX3L2JANnWHu0T35kj8XNkLzFO5JhRtQgj8Bn7m 7crFSJgz6Z1oxd3yf+9KvOjkFAeGA5A7Zn3PbJflR35/pySnCkZwBiYf+qUH5LM3OofL dCiQ== X-Gm-Message-State: AO0yUKXZAb9KNOW3T0zGvCEmSTo2K9+zebs0o4i4wIYfkpcfwIjg9GxW 88nVAvMCOBxs/5I6Groexje+K0NwL+o= X-Google-Smtp-Source: AK7set+0HAdxADTN2FO/Z0fRf4ofzT2LR5rmVb8+PTmQOv+9aozgpMydP1xe5YnwORoBiu9TiNWbXw== X-Received: by 2002:a17:902:d509:b0:19c:65bd:d44b with SMTP id b9-20020a170902d50900b0019c65bdd44bmr20072836plg.60.1678227874822; Tue, 07 Mar 2023 14:24:34 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:34 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 09/12] profiles: Add initial code for csip plugin Date: Tue, 7 Mar 2023 14:24:19 -0800 Message-Id: <20230307222422.2608483-9-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sathish Narasimman This adds initial code for csip plugin which handles Coordinated set identification Profile and Coordinated Set Identification Service. --- Makefile.plugins | 5 + configure.ac | 4 + profiles/audio/csip.c | 363 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 profiles/audio/csip.c diff --git a/Makefile.plugins b/Makefile.plugins index 20cac384ef44..0f119e8714b7 100644 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -131,3 +131,8 @@ if VCP builtin_modules += vcp builtin_sources += profiles/audio/vcp.c endif + +if CSIP +builtin_modules += csip +builtin_sources += profiles/audio/csip.c +endif diff --git a/configure.ac b/configure.ac index 515cdf1461eb..6f890110f554 100644 --- a/configure.ac +++ b/configure.ac @@ -207,6 +207,10 @@ AC_ARG_ENABLE(vcp, AS_HELP_STRING([--disable-vcp], [disable VCP profile]), [enable_vcp=${enableval}]) AM_CONDITIONAL(VCP, test "${enable_vcp}" != "no") +AC_ARG_ENABLE(csip, AS_HELP_STRING([--disable-csip], + [disable CSIP profile]), [enable_csip=${enableval}]) +AM_CONDITIONAL(CSIP, test "${enable_csip}" != "no") + AC_ARG_ENABLE(tools, AS_HELP_STRING([--disable-tools], [disable Bluetooth tools]), [enable_tools=${enableval}]) AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no") diff --git a/profiles/audio/csip.c b/profiles/audio/csip.c new file mode 100644 index 000000000000..c273c02b8e76 --- /dev/null +++ b/profiles/audio/csip.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gdbus/gdbus.h" + +#include "lib/bluetooth.h" +#include "lib/hci.h" +#include "lib/sdp.h" +#include "lib/uuid.h" + +#include "src/dbus-common.h" +#include "src/shared/util.h" +#include "src/shared/att.h" +#include "src/shared/queue.h" +#include "src/shared/gatt-db.h" +#include "src/shared/gatt-client.h" +#include "src/shared/gatt-server.h" +#include "src/shared/csip.h" + +#include "btio/btio.h" +#include "src/plugin.h" +#include "src/adapter.h" +#include "src/gatt-database.h" +#include "src/device.h" +#include "src/profile.h" +#include "src/service.h" +#include "src/log.h" +#include "src/error.h" +#include "src/btd.h" + +#define CSIS_UUID_STR "00001846-0000-1000-8000-00805f9b34fb" + +struct csip_data { + struct btd_device *device; + struct btd_service *service; + struct bt_csip *csip; + unsigned int ready_id; +}; + +static struct queue *sessions; + +static void csip_debug(const char *str, void *user_data) +{ + DBG_IDX(0xffff, "%s", str); +} + +static struct csip_data *csip_data_new(struct btd_device *device) +{ + struct csip_data *data; + + data = new0(struct csip_data, 1); + data->device = device; + + return data; +} + +static bool csip_ltk_read(struct bt_csip *csip, uint8_t k[16], void *user_data) +{ + /* TODO: Retrieve LTK using device object */ + return false; +} + +static void csip_data_add(struct csip_data *data) +{ + DBG("data %p", data); + + if (queue_find(sessions, NULL, data)) { + error("data %p already added", data); + return; + } + + bt_csip_set_debug(data->csip, csip_debug, NULL, NULL); + + bt_csip_set_sirk(data->csip, btd_opts.csis.encrypt, btd_opts.csis.sirk, + btd_opts.csis.size, btd_opts.csis.rank, + csip_ltk_read, data); + + if (!sessions) + sessions = queue_new(); + + queue_push_tail(sessions, data); + + if (data->service) + btd_service_set_user_data(data->service, data); +} + +static int csip_disconnect(struct btd_service *service) +{ + struct csip_data *data = btd_service_get_user_data(service); + + bt_csip_detach(data->csip); + + btd_service_disconnecting_complete(service, 0); + + return 0; +} + +static bool match_data(const void *data, const void *match_data) +{ + const struct csip_data *vdata = data; + const struct bt_csip *csip = match_data; + + return vdata->csip == csip; +} + +static void csip_data_free(struct csip_data *data) +{ + if (data->service) { + btd_service_set_user_data(data->service, NULL); + bt_csip_set_user_data(data->csip, NULL); + } + + bt_csip_ready_unregister(data->csip, data->ready_id); + bt_csip_unref(data->csip); + free(data); +} + +static void csip_data_remove(struct csip_data *data) +{ + DBG("data %p", data); + + if (!queue_remove(sessions, data)) + return; + + csip_data_free(data); + + if (queue_isempty(sessions)) { + queue_destroy(sessions, NULL); + sessions = NULL; + } +} + +static void csip_detached(struct bt_csip *csip, void *user_data) +{ + struct csip_data *data; + + DBG("%p", csip); + + data = queue_find(sessions, match_data, csip); + if (!data) { + error("Unable to find csip session"); + return; + } + + /* If there is a service it means there is CSIS thus we can keep + * instance allocated. + */ + if (data->service) + return; + + csip_data_remove(data); +} + +static void csip_attached(struct bt_csip *csip, void *user_data) +{ + struct csip_data *data; + struct bt_att *att; + struct btd_device *device; + + DBG("%p", csip); + + data = queue_find(sessions, match_data, csip); + if (data) + return; + + att = bt_csip_get_att(csip); + if (!att) + return; + + device = btd_adapter_find_device_by_fd(bt_att_get_fd(att)); + if (!device) { + error("Unable to find device"); + return; + } + + data = csip_data_new(device); + data->csip = csip; + + csip_data_add(data); + +} + +static int csip_server_probe(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct btd_gatt_database *database = btd_adapter_get_database(adapter); + + DBG("CSIP path %s", adapter_get_path(adapter)); + + bt_csip_add_db(btd_gatt_database_get_db(database)); + + return 0; +} + +static void csip_server_remove(struct btd_profile *p, + struct btd_adapter *adapter) +{ + DBG("CSIP remove Adapter"); +} + +static int csip_accept(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct bt_gatt_client *client = btd_device_get_gatt_client(device); + struct csip_data *data = btd_service_get_user_data(service); + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + if (!data) { + error("CSIP service not handled by profile"); + return -EINVAL; + } + + if (!bt_csip_attach(data->csip, client)) { + error("CSIP unable to attach"); + return -EINVAL; + } + + btd_service_connecting_complete(service, 0); + + return 0; +} + +static void csip_ready(struct bt_csip *csip, void *user_data) +{ + struct btd_service *service = user_data; + struct btd_device *device = btd_service_get_device(service); + uint8_t type, size, rank; + uint8_t k[16]; + + DBG("csip %p", csip); + + if (!bt_csip_get_sirk(csip, &type, k, &size, &rank)) { + error("Unable to read SIRK"); + return; + } + + btd_device_add_set(device, type == BT_CSIP_SIRK_ENCRYPT ? true : false, + k, size, rank); +} + +static int csip_probe(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct btd_adapter *adapter = device_get_adapter(device); + struct btd_gatt_database *database = btd_adapter_get_database(adapter); + struct csip_data *data = btd_service_get_user_data(service); + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + /* Ignore, if we were probed for this device already */ + if (data) { + error("Profile probed twice for the same device!"); + return -EINVAL; + } + + data = csip_data_new(device); + data->service = service; + + data->csip = bt_csip_new(btd_gatt_database_get_db(database), + btd_device_get_gatt_db(device)); + if (!data->csip) { + error("Unable to create CSIP instance"); + free(data); + return -EINVAL; + } + + csip_data_add(data); + + data->ready_id = bt_csip_ready_register(data->csip, csip_ready, service, + NULL); + + bt_csip_set_user_data(data->csip, service); + + return 0; +} + +static void csip_remove(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct csip_data *data; + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + data = btd_service_get_user_data(service); + if (!data) { + error("CSIP service not handled by profile"); + return; + } + + csip_data_remove(data); +} + +static struct btd_profile csip_profile = { + .name = "csip", + .priority = BTD_PROFILE_PRIORITY_MEDIUM, + .remote_uuid = CSIS_UUID_STR, + + .device_probe = csip_probe, + .device_remove = csip_remove, + + .accept = csip_accept, + .disconnect = csip_disconnect, + + .adapter_probe = csip_server_probe, + .adapter_remove = csip_server_remove, +}; + +static unsigned int csip_id; + +static int csip_init(void) +{ + if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) { + warn("D-Bus experimental not enabled"); + return -ENOTSUP; + } + + btd_profile_register(&csip_profile); + csip_id = bt_csip_register(csip_attached, csip_detached, NULL); + + return 0; +} + +static void csip_exit(void) +{ + if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) { + btd_profile_unregister(&csip_profile); + bt_csip_unregister(csip_id); + } +} + +BLUETOOTH_PLUGIN_DEFINE(csip, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, + csip_init, csip_exit) From patchwork Tue Mar 7 22:24:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660706 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6A21C742A7 for ; Tue, 7 Mar 2023 22:26:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230221AbjCGW0G (ORCPT ); Tue, 7 Mar 2023 17:26:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230182AbjCGWZo (ORCPT ); Tue, 7 Mar 2023 17:25:44 -0500 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42E4CB04A9 for ; Tue, 7 Mar 2023 14:25:08 -0800 (PST) Received: by mail-pj1-x102a.google.com with SMTP id y2so14722017pjg.3 for ; Tue, 07 Mar 2023 14:25:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227876; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=IQZKy3IHJaNGPM4dHl2hvvgbBOAHVYSI4LpSoo6O9E0=; b=FnpjHpyyIRq3F4KyNRd/2J+m4oGYuozWR7AClty5ijloHgMJO3Qr2xKKAz1MZORlfJ Ho2MdN+9hRBHOtVXysD4FEvMYNWR9nsH/FOGWEAeSkPDPoCI2NCB7798RPFSVYjE30Kk hNx2HNH/mFmrf7qxW1ydNCITDT5Btuh/t+69UFXc/j1bY/bhQlcasyUWefuexmcjaMAf OSNiao1CxkLN0E118kLXzKwYhf06dEAovWbWj4vkgmA7oxrr2gUbHc5RQIog974QwfIv Wng/4kzQ/DkMXSjHrlNm4eAlOiv5Wv41x9mIvAJ99a3NuUM8Wgd35nnc6qQfZbKm4nYW 8M8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227876; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IQZKy3IHJaNGPM4dHl2hvvgbBOAHVYSI4LpSoo6O9E0=; b=7cNFx/ew3w5wecdcltl6Oyob/TTbGmu89Tv8ysmAxRviEFc7Yl4yu/d11R7y7mKvPK gLaOxqkystf++a5OyyFgXpExJRUqlsskIDgwmGRsOn6xkdh/pgZw6S6eWwU3BDOHifCd JiX1I4YpIf0TzWJGonZlDwxCs557YzQhX9rWihyQRMP5fRVzJtgD+wQaY6oPwASplE/g 8O3vP4LWVthPbYUlPVGwcnMyU0oMC0wIz60PBMReZt4fWey9cv3hjiEkcArw6tD+ydCh rXGpYO66xtimU03M5MVj8yHnTK5L4rwoS58N1fi0pcYklIN0iqid9ZOBD9ahYXMbstCW arMw== X-Gm-Message-State: AO0yUKUJqoNKZl15LHX9fXFpV1t2/Cz9w3raGCUWXwe4OSuM7lbgpM6W t5W9nFqn3KxIdi9kc2OP25Ou3bePcOM= X-Google-Smtp-Source: AK7set80WKNLeAac59Q/5LcJvqTEcS34ZMtaujZZTw/mCPe9/U5yAcWfQuJ+aHfEqXdYfpjgpi+TPg== X-Received: by 2002:a17:903:2450:b0:19c:e484:b45 with SMTP id l16-20020a170903245000b0019ce4840b45mr18269930pls.27.1678227876133; Tue, 07 Mar 2023 14:24:36 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:35 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 10/12] tools: Add support to generate RSI using SIRK Date: Tue, 7 Mar 2023 14:24:20 -0800 Message-Id: <20230307222422.2608483-10-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sathish Narasimman The patch helps to generate Resolvable set identifier adv data. which can be used as ADV data during advertisement. It will be used to identify the device as part of setmember for Coordinated set identification profile. Example: $advtest -i "761FAE703ED681F0C50B34155B6434FB" SIRK: 761FAE703ED681F0C50B34155B6434FB RSI: 0x71 0xcb 0xbc 0x7e 0x01 0x84 Random: bccb71 Hash: 84017e --- tools/advtest.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/tools/advtest.c b/tools/advtest.c index de036e783325..9ef69ed5124a 100644 --- a/tools/advtest.c +++ b/tools/advtest.c @@ -13,6 +13,13 @@ #include #endif +#include + +#include +#include +#include +#include + #include #include "lib/bluetooth.h" @@ -32,6 +39,9 @@ "\xe1\x23\x99\xc1\xca\x9a\xc3\x31" #define SCAN_IRK "\xfa\x73\x09\x11\x3f\x03\x37\x0f" \ "\xf4\xf9\x93\x1e\xf9\xa3\x63\xa6" +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif static struct mgmt *mgmt; static uint16_t index1 = MGMT_INDEX_NONE; @@ -43,13 +53,73 @@ static struct bt_hci *scan_dev; static void print_rpa(const uint8_t addr[6]) { - printf(" Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + printf(" RSI:\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); printf(" Random: %02x%02x%02x\n", addr[3], addr[4], addr[5]); printf(" Hash: %02x%02x%02x\n", addr[0], addr[1], addr[2]); } +static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) +{ + size_t i, len; + + len = MIN((strlen(hexstr) / 2), buflen); + memset(buf, 0, len); + + for (i = 0; i < len; i++) + if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1) + continue; + + + return len; +} + +static bool get_random_bytes(void *buf, size_t num_bytes) +{ + ssize_t len; + int fd; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + return false; + + len = read(fd, buf, num_bytes); + + close(fd); + + if (len < 0) + return false; + + return true; +} + +static void generate_rsi(char *val) +{ + uint8_t sirk[16], hash[3]; + uint8_t rsi[6] = {0}; + + hex2bin(val, sirk, sizeof(sirk)); + + get_random_bytes(&rsi[3], 3); + + rsi[5] &= 0x3f; /* Clear 2 msb */ + rsi[5] |= 0x40; /* Set 2nd msb */ + + crypto = bt_crypto_new(); + if (!crypto) { + fprintf(stderr, "Failed to open crypto interface\n"); + mainloop_exit_failure(); + return; + } + + bt_crypto_ah(crypto, sirk, rsi + 3, hash); + memcpy(rsi, hash, 3); + + print_rpa(rsi); +} + + static void scan_le_adv_report(const void *data, uint8_t size, void *user_data) { @@ -351,9 +421,11 @@ static void usage(void) printf("\tadvtest [options]\n"); printf("options:\n" "\t-h, --help Show help options\n"); + printf(" \t-i <128bit SIRK>, Generate RSI ADV Data\n"); } static const struct option main_options[] = { + { "hash", no_argument, NULL, 'i' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { } @@ -366,11 +438,15 @@ int main(int argc ,char *argv[]) for (;;) { int opt; - opt = getopt_long(argc, argv, "vh", main_options, NULL); + opt = getopt_long(argc, argv, "i:vh", main_options, NULL); if (opt < 0) break; switch (opt) { + case 'i': + printf("SIRK: %s\n", optarg); + generate_rsi(optarg); + return EXIT_SUCCESS; case 'v': printf("%s\n", VERSION); return EXIT_SUCCESS; From patchwork Tue Mar 7 22:24:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C98F1C6FD1E for ; Tue, 7 Mar 2023 22:26:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230211AbjCGW0J (ORCPT ); Tue, 7 Mar 2023 17:26:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230264AbjCGWZq (ORCPT ); Tue, 7 Mar 2023 17:25:46 -0500 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D0D87B06D5 for ; Tue, 7 Mar 2023 14:25:09 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id kb15so14745617pjb.1 for ; Tue, 07 Mar 2023 14:25:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227877; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=r8B2lXwNrFIHbcQjST1r7bCRbxcqRLF67pR9ltHnW/U=; b=Z+L/NsIyf+qDxs8Ibln4mT+e767e5F5eTELkXRYM/8PURXtjLf0df9OlszFjQIWVUk ayPDBDE2aSUPESdSs7uGZuolhpJRelHYEBnkxuWisJFqRah735mCIMNjILzuyOpAZq0o Ei/6WieImpJNuFbZK6CUMpjjLN1pq4CU2NrqUSbHGwB7VEmORjdV8Xz9+dhVEjJCaVaE yj3jWrLL+iU17ZG2brSIDWOcgLdaSLJQatY+6pTt498W3cODmhS1vpC0+MZDt7SyNqdP TMf108ICXiV1gwEXW7WbWjG051LA8xvwAwNAXA6cORfO7iW0jhomqFSFIJKKbSt8x9M7 f0TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227877; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=r8B2lXwNrFIHbcQjST1r7bCRbxcqRLF67pR9ltHnW/U=; b=XNqhaQ3WcEuyHEgEnMrXkQlztYPtXn+WOUhHp+pD7sOtimUqF/vuaM3JpihIkm9Hmm 9GH+kUUjm0jf5P6NO1dGTU3IyWbtBMZdDSYG9+6MG3+VmlGeTERIs129XU6kGUdhxAEP x8urztEBTSrDFZkjlYM/Gph6foCSf2X9zGoM7ohmdiANKzlc/qiQX/1HBy3TCl8ZgWkL RCYMSi/pK2g9auyPnP71HHwYfS8avBmNKz8sU1W2h5ETxDTB4DtqDd5c6b+j4ebQ2IAs m+ToP8GjzXyiqrW9UzW6QxfvE7U6xjR05/kX5n+Jux5tfvbR4m678bRTfUFv3oWQCsp4 ZVFw== X-Gm-Message-State: AO0yUKVVqSIno4JtghTii7NhMElc5xw7PGwhUHChOhGT9IDZGHF3rF1Y 0Ta1z+2EG5INedrX+g3eEsArFnj7s5I= X-Google-Smtp-Source: AK7set8it+YfeA8ZtDJc4B2LL9/up1PBgBfa5z4eBM+IBhqzjfq/e6vDkdorCz+319sW4FVkWh7YLA== X-Received: by 2002:a17:902:d512:b0:196:704e:2c9a with SMTP id b18-20020a170902d51200b00196704e2c9amr18977455plg.22.1678227877399; Tue, 07 Mar 2023 14:24:37 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:36 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 11/12] client: Add support for DeviceSet proxy Date: Tue, 7 Mar 2023 14:24:21 -0800 Message-Id: <20230307222422.2608483-11-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz --- client/main.c | 113 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 10 deletions(-) diff --git a/client/main.c b/client/main.c index e5cf1e203ed1..e4a39896b2c6 100644 --- a/client/main.c +++ b/client/main.c @@ -51,6 +51,7 @@ struct adapter { GDBusProxy *ad_proxy; GDBusProxy *adv_monitor_proxy; GList *devices; + GList *sets; }; static struct adapter *default_ctrl; @@ -232,7 +233,7 @@ static void print_experimental(GDBusProxy *proxy) } } -static gboolean device_is_child(GDBusProxy *device, GDBusProxy *parent) +static gboolean proxy_is_child(GDBusProxy *device, GDBusProxy *parent) { DBusMessageIter iter; const char *adapter, *path; @@ -269,14 +270,14 @@ static gboolean service_is_child(GDBusProxy *service) "org.bluez.Device1") != NULL; } -static struct adapter *find_parent(GDBusProxy *device) +static struct adapter *find_parent(GDBusProxy *proxy) { GList *list; for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) { struct adapter *adapter = list->data; - if (device_is_child(device, adapter->proxy) == TRUE) + if (proxy_is_child(proxy, adapter->proxy) == TRUE) return adapter; } return NULL; @@ -399,6 +400,27 @@ static void admon_manager_added(GDBusProxy *proxy) adv_monitor_register_app(dbus_conn); } +static void print_set(GDBusProxy *proxy, const char *description) +{ + bt_shell_printf("%s%s%sDeviceSet %s\n", + description ? "[" : "", + description ? : "", + description ? "] " : "", + g_dbus_proxy_get_path(proxy)); +} + +static void set_added(GDBusProxy *proxy) +{ + struct adapter *adapter = find_parent(proxy); + + if (!adapter) + return; + + adapter->sets = g_list_append(adapter->sets, proxy); + print_set(proxy, COLORED_NEW); + bt_shell_set_env(g_dbus_proxy_get_path(proxy), proxy); +} + static void proxy_added(GDBusProxy *proxy, void *user_data) { const char *interface; @@ -434,6 +456,8 @@ static void proxy_added(GDBusProxy *proxy, void *user_data) } else if (!strcmp(interface, "org.bluez.AdvertisementMonitorManager1")) { admon_manager_added(proxy); + } else if (!strcmp(interface, "org.bluez.DeviceSet1")) { + set_added(proxy); } } @@ -484,6 +508,7 @@ static void adapter_removed(GDBusProxy *proxy) ctrl_list = g_list_remove_link(ctrl_list, ll); g_list_free(adapter->devices); + g_list_free(adapter->sets); g_free(adapter); g_list_free(ll); return; @@ -491,6 +516,19 @@ static void adapter_removed(GDBusProxy *proxy) } } +static void set_removed(GDBusProxy *proxy) +{ + struct adapter *adapter = find_parent(proxy); + + if (!adapter) + return; + + adapter->sets = g_list_remove(adapter->sets, proxy); + + print_set(proxy, COLORED_DEL); + bt_shell_set_env(g_dbus_proxy_get_path(proxy), NULL); +} + static void proxy_removed(GDBusProxy *proxy, void *user_data) { const char *interface; @@ -531,6 +569,8 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data) } else if (!strcmp(interface, "org.bluez.AdvertisementMonitorManager1")) { adv_monitor_remove_manager(dbus_conn); + } else if (!strcmp(interface, "org.bluez.DeviceSet1")) { + set_removed(proxy); } } @@ -557,7 +597,7 @@ static void property_changed(GDBusProxy *proxy, const char *name, interface = g_dbus_proxy_get_interface(proxy); if (!strcmp(interface, "org.bluez.Device1")) { - if (default_ctrl && device_is_child(proxy, + if (default_ctrl && proxy_is_child(proxy, default_ctrl->proxy) == TRUE) { DBusMessageIter addr_iter; char *str; @@ -1559,6 +1599,39 @@ static struct GDBusProxy *find_device(int argc, char *argv[]) return proxy; } +static struct GDBusProxy *find_set(int argc, char *argv[]) +{ + GDBusProxy *proxy; + + if (check_default_ctrl() == FALSE) + return NULL; + + proxy = find_proxies_by_path(default_ctrl->sets, argv[1]); + if (!proxy) { + bt_shell_printf("DeviceSet %s not available\n", argv[1]); + return NULL; + } + + return proxy; +} + +static void cmd_set_info(int argc, char *argv[]) +{ + GDBusProxy *proxy; + + proxy = find_set(argc, argv); + if (!proxy) + return bt_shell_noninteractive_quit(EXIT_FAILURE); + + bt_shell_printf("DeviceSet %s\n", g_dbus_proxy_get_path(proxy)); + + print_property(proxy, "AutoConnect"); + print_property(proxy, "Devices"); + print_property(proxy, "Size"); + + return bt_shell_noninteractive_quit(EXIT_SUCCESS); +} + static void cmd_info(int argc, char *argv[]) { GDBusProxy *proxy; @@ -1568,7 +1641,7 @@ static void cmd_info(int argc, char *argv[]) proxy = find_device(argc, argv); if (!proxy) - return bt_shell_noninteractive_quit(EXIT_FAILURE); + return cmd_set_info(argc, argv); if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE) return bt_shell_noninteractive_quit(EXIT_FAILURE); @@ -1605,6 +1678,7 @@ static void cmd_info(int argc, char *argv[]) print_property(proxy, "TxPower"); print_property(proxy, "AdvertisingFlags"); print_property(proxy, "AdvertisingData"); + print_property(proxy, "Sets"); battery_proxy = find_proxies_by_path(battery_proxies, g_dbus_proxy_get_path(proxy)); @@ -2298,11 +2372,13 @@ static char *generic_generator(const char *text, int state, index++; - if (g_dbus_proxy_get_property(proxy, property, &iter) == FALSE) + if (!property) + str = g_dbus_proxy_get_path(proxy); + else if (g_dbus_proxy_get_property(proxy, property, &iter)) + dbus_message_iter_get_basic(&iter, &str); + else continue; - dbus_message_iter_get_basic(&iter, &str); - if (!strncasecmp(str, text, len)) return strdup(str); } @@ -2348,6 +2424,23 @@ static char *dev_generator(const char *text, int state) default_ctrl ? default_ctrl->devices : NULL, "Address"); } +static char *set_generator(const char *text, int state) +{ + return generic_generator(text, state, + default_ctrl ? default_ctrl->sets : NULL, NULL); +} + +static char *dev_set_generator(const char *text, int state) +{ + char *str; + + str = dev_generator(text, state); + if (str) + return str; + + return set_generator(text, state); +} + static char *attribute_generator(const char *text, int state) { return gatt_attribute_generator(text, state); @@ -2965,8 +3058,8 @@ static const struct bt_shell_menu main_menu = { { "set-alias", "", cmd_set_alias, "Set device alias" }, { "scan", "", cmd_scan, "Scan for devices", scan_generator }, - { "info", "[dev]", cmd_info, "Device information", - dev_generator }, + { "info", "[dev/set]", cmd_info, "Device/Set information", + dev_set_generator }, { "pair", "[dev]", cmd_pair, "Pair with device", dev_generator }, { "cancel-pairing", "[dev]", cmd_cancel_pairing, From patchwork Tue Mar 7 22:24:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 660001 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E664BC678D5 for ; Tue, 7 Mar 2023 22:26:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230228AbjCGW0H (ORCPT ); Tue, 7 Mar 2023 17:26:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52958 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230240AbjCGWZq (ORCPT ); Tue, 7 Mar 2023 17:25:46 -0500 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6EB71B06DD for ; Tue, 7 Mar 2023 14:25:10 -0800 (PST) Received: by mail-pj1-x102f.google.com with SMTP id m20-20020a17090ab79400b00239d8e182efso187752pjr.5 for ; Tue, 07 Mar 2023 14:25:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678227878; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Z1IU8LiWwZeoZ/1lc6uZFO7QKOeog+W2EZMCDjvEpLE=; b=gSq9C3z3ElE7vwAVygN50LcQN0FYB+pGpPYfTeHN3/UJCAzfFYxNdZrGYsYASnNblL 5sI6W6Rzrq/zzo52klf2HPvCXoSWDFcORmnQPiNjxI1VfRpgRFepHiKYvT4kpvKmNmM1 9i0damE7357bmEPiczd0V4XJOG5il4lmepG1Q33b7DtAPBeSKjxoAXicbdwogKPitaa0 StLuMLAPKtHAAfOFS2I2tPMUEPaXUgcz+e1e2X/myZSObdvo8iiwY743CfeErKfl3S9W 9BnBu7JgcAMVrfHOca7U9sXdqFeC5vMMYJICs+VXZjkG+VV8dQKZSkmInW0iy5V8vM/S LHQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678227878; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Z1IU8LiWwZeoZ/1lc6uZFO7QKOeog+W2EZMCDjvEpLE=; b=JetJfRgcHK1bj43Xy7GzxOL8fzWJ7w3VqsMEAOFMU1LLGn0Fhqu05OCtKzJy/9IXrY +uM6b+C8dH9RaRs5lW8LrWtKPuL7Y13P2t9k6Yd9KFvZDg1emUsYEeylExRllr3jA6mb gsI8PkcdGp9izmmBDjId3GqujYToOr2UjiwWM5R+N36fqB1/goQRohkfs3AiBfsneNp1 GtQC4I+tgTM72GjQSsIJSnZyV9GdAwPCAYyWyJmGjZyuQSMAUKqVu64lBQ6OJXFoBM0M szle2PCOR1Ib4lKna0LK4TjjYKz5KCiC9WBfkY+2vlj8mLxPmtk99pCJ0BKHDu0puGg5 bkJg== X-Gm-Message-State: AO0yUKWvDnPpAXaivb6OdglJ/p5YdpQN9+YizDZgXBgQ2oTejucQpp6J IIx5iCPHFnRkkG1va8WdyysmN7g8tEQ= X-Google-Smtp-Source: AK7set/9eNQAfULKWfO1B3cLnisHqMRtar3Kt0GSm+tu9pS9BEPQ1fFI50buDouk/XrqtPA7ZANQBg== X-Received: by 2002:a17:903:22c1:b0:19e:ba2c:27ec with SMTP id y1-20020a17090322c100b0019eba2c27ecmr12638088plg.11.1678227878532; Tue, 07 Mar 2023 14:24:38 -0800 (PST) Received: from lvondent-mobl4.. (c-71-59-129-171.hsd1.or.comcast.net. [71.59.129.171]) by smtp.gmail.com with ESMTPSA id d18-20020a170902729200b0019c901b35ecsm8814392pll.106.2023.03.07.14.24.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Mar 2023 14:24:38 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [RFC v2 12/12] client: Use AdvertisingFlags when available Date: Tue, 7 Mar 2023 14:24:22 -0800 Message-Id: <20230307222422.2608483-12-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307222422.2608483-1-luiz.dentz@gmail.com> References: <20230307222422.2608483-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This prints devices not discoverable in grey so the user are able to distict when for example set members are actually visible. --- client/main.c | 79 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/client/main.c b/client/main.c index e4a39896b2c6..79895015d6a6 100644 --- a/client/main.c +++ b/client/main.c @@ -24,6 +24,7 @@ #include "src/shared/shell.h" #include "src/shared/util.h" +#include "src/shared/ad.h" #include "gdbus/gdbus.h" #include "print.h" #include "agent.h" @@ -143,10 +144,32 @@ static void print_adapter(GDBusProxy *proxy, const char *description) } +#define DISTANCE_VAL_INVALID 0x7FFF + +static struct set_discovery_filter_args { + char *transport; + char *pattern; + dbus_uint16_t rssi; + dbus_int16_t pathloss; + char **uuids; + size_t uuids_len; + dbus_bool_t duplicate; + dbus_bool_t discoverable; + bool set; + bool active; + unsigned int timeout; +} filter = { + .rssi = DISTANCE_VAL_INVALID, + .pathloss = DISTANCE_VAL_INVALID, + .set = true, +}; + static void print_device(GDBusProxy *proxy, const char *description) { DBusMessageIter iter; const char *address, *name; + uint8_t *flags; + int flags_len = 0; if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE) return; @@ -158,11 +181,39 @@ static void print_device(GDBusProxy *proxy, const char *description) else name = ""; + if (g_dbus_proxy_get_property(proxy, "AdvertisingFlags", &iter)) { + DBusMessageIter array; + + dbus_message_iter_recurse(&iter, &array); + dbus_message_iter_get_fixed_array(&array, &flags, &flags_len); + } + + if (!flags_len) + goto done; + + if (!(flags[0] & (BT_AD_FLAG_LIMITED | BT_AD_FLAG_GENERAL))) { + /* Only print hidden/non-discoverable if filter.discoverable is + * not set. + */ + if (filter.discoverable) + return; + + bt_shell_printf("%s%s%s" COLOR_BOLDGRAY "Device %s %s" + COLOR_OFF "\n", + description ? "[" : "", + description ? : "", + description ? "] " : "", + address, name); + + return; + } + +done: bt_shell_printf("%s%s%sDevice %s %s\n", - description ? "[" : "", - description ? : "", - description ? "] " : "", - address, name); + description ? "[" : "", + description ? : "", + description ? "] " : "", + address, name); } static void print_uuid(const char *label, const char *uuid) @@ -1133,26 +1184,6 @@ static void cmd_default_agent(int argc, char *argv[]) agent_default(dbus_conn, agent_manager); } -#define DISTANCE_VAL_INVALID 0x7FFF - -static struct set_discovery_filter_args { - char *transport; - char *pattern; - dbus_uint16_t rssi; - dbus_int16_t pathloss; - char **uuids; - size_t uuids_len; - dbus_bool_t duplicate; - dbus_bool_t discoverable; - bool set; - bool active; - unsigned int timeout; -} filter = { - .rssi = DISTANCE_VAL_INVALID, - .pathloss = DISTANCE_VAL_INVALID, - .set = true, -}; - static void start_discovery_reply(DBusMessage *message, void *user_data) { dbus_bool_t enable = GPOINTER_TO_UINT(user_data);