[RFC v2 07/12] main.conf: Add CSIP profile configurable options

Luiz Augusto von Dentz
2023-03-07T22:25:59Z

From: Sathish Narasimman <sathish.narasimman@intel.com>

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:
--
2.39.2