From: Sathish Narasimman <sathish.narasimman@xxxxxxxxx> 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 f7ccbb49eb04..235d1a6ed397 100644 --- a/src/main.conf +++ b/src/main.conf @@ -258,6 +258,31 @@ KernelExperimental = 6fbaf188-05e0-496a-9885-d6ddfdb4e03e # 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