This set add support for privacy mode in BfA.
This is in order to follow Android Lollipop
v2: Typo fix (important one) in patch 3/4.
v3: Handle Marcel comments (patches 3-4) plus self review (patches 2,5)
Lukasz Rymanowski (4):
android/bluetooth: Start keep IRK for adapter
android/bluetooth: Store IRK when storing adapter config
android/bluetooth: Load IRK on adapter start
android/bluetooth: Enable LE privacy mode on BfA startup
android/bluetooth.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
--
1.8.4
Hi Szymon,
On Tue, Dec 16, 2014 at 10:37 PM, Szymon Janc <[email protected]> wrote:
> Hi Łukasz,
>
> On Wednesday 10 December 2014 20:15:48 Lukasz Rymanowski wrote:
>> Lets follow Android Lollipop behaviour and enable privacy on
>> startup.
>> ---
>> android/bluetooth.c | 29 +++++++++++++++++++++++++++++
>> 1 file changed, 29 insertions(+)
>>
>> diff --git a/android/bluetooth.c b/android/bluetooth.c
>> index 4c359d0..54e3d97 100644
>> --- a/android/bluetooth.c
>> +++ b/android/bluetooth.c
>> @@ -3423,6 +3423,32 @@ static void clear_auto_connect_list(void)
>> error("Could not clear auto connect list");
>> }
>>
>> +static void set_privacy_complete(uint8_t status, uint16_t length,
>> + const void *param, void *user_data)
>> +{
>> + if (status != MGMT_STATUS_SUCCESS)
>> + error("Failed to set privacy mode: %s (0x%02x)",
>> + mgmt_errstr(status), status);
>> +}
>> +
>> +static void set_privacy(void)
>> +{
>> + struct mgmt_cp_set_privacy cp;
>> +
>> + if (!local_irk_is_valid())
>> + goto failed;
>> +
>> + cp.privacy = 0x01;
>> + memcpy(cp.irk, adapter.irk, sizeof(adapter.irk));
>> +
>> + if (mgmt_send(mgmt_if, MGMT_OP_SET_PRIVACY, adapter.index, sizeof(cp),
>> + &cp, set_privacy_complete, NULL, NULL) > 0)
>> + return;
>> +
>> +failed:
>> + error("Could not set privacy mode");
>> +}
>> +
>> static void read_info_complete(uint8_t status, uint16_t length,
>> const void *param, void *user_data)
>> {
>> @@ -3497,6 +3523,9 @@ static void read_info_complete(uint8_t status,
>> uint16_t length, if (missing_settings & MGMT_SETTING_BONDABLE)
>> set_mode(MGMT_OP_SET_BONDABLE, 0x01);
>>
>> + if (missing_settings & MGMT_SETTING_PRIVACY)
>> + set_privacy();
>> +
>> load_devices_info(cb);
>> load_devices_cache();
>
> Shouldn't we first configure a static random address?
Why?
\Lukasz
>
> --
> Szymon K. Janc
> [email protected]
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Łukasz,
On Wednesday 10 December 2014 20:15:48 Lukasz Rymanowski wrote:
> Lets follow Android Lollipop behaviour and enable privacy on
> startup.
> ---
> android/bluetooth.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/android/bluetooth.c b/android/bluetooth.c
> index 4c359d0..54e3d97 100644
> --- a/android/bluetooth.c
> +++ b/android/bluetooth.c
> @@ -3423,6 +3423,32 @@ static void clear_auto_connect_list(void)
> error("Could not clear auto connect list");
> }
>
> +static void set_privacy_complete(uint8_t status, uint16_t length,
> + const void *param, void *user_data)
> +{
> + if (status != MGMT_STATUS_SUCCESS)
> + error("Failed to set privacy mode: %s (0x%02x)",
> + mgmt_errstr(status), status);
> +}
> +
> +static void set_privacy(void)
> +{
> + struct mgmt_cp_set_privacy cp;
> +
> + if (!local_irk_is_valid())
> + goto failed;
> +
> + cp.privacy = 0x01;
> + memcpy(cp.irk, adapter.irk, sizeof(adapter.irk));
> +
> + if (mgmt_send(mgmt_if, MGMT_OP_SET_PRIVACY, adapter.index, sizeof(cp),
> + &cp, set_privacy_complete, NULL, NULL) > 0)
> + return;
> +
> +failed:
> + error("Could not set privacy mode");
> +}
> +
> static void read_info_complete(uint8_t status, uint16_t length,
> const void *param, void *user_data)
> {
> @@ -3497,6 +3523,9 @@ static void read_info_complete(uint8_t status,
> uint16_t length, if (missing_settings & MGMT_SETTING_BONDABLE)
> set_mode(MGMT_OP_SET_BONDABLE, 0x01);
>
> + if (missing_settings & MGMT_SETTING_PRIVACY)
> + set_privacy();
> +
> load_devices_info(cb);
> load_devices_cache();
Shouldn't we first configure a static random address?
--
Szymon K. Janc
[email protected]
Hi Łukasz,
On Wednesday 10 December 2014 20:15:45 Lukasz Rymanowski wrote:
> ---
> android/bluetooth.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/android/bluetooth.c b/android/bluetooth.c
> index 48ca231..e9c5be1 100644
> --- a/android/bluetooth.c
> +++ b/android/bluetooth.c
> @@ -176,6 +176,8 @@ static struct {
>
> char *name;
>
> + uint8_t irk[16];
> +
> uint8_t max_advert_instance;
> uint8_t rpa_offload_supported;
> uint8_t max_irk_list_size;
> @@ -196,6 +198,7 @@ static struct {
> .index = MGMT_INDEX_NONE,
> .dev_class = 0,
> .name = NULL,
> + .irk = {0},
> .max_advert_instance = 0,
> .rpa_offload_supported = 0,
> .max_irk_list_size = 0,
I don't think we need to keep IRK in memory.
I'd just try to load it (if not present generate and store) and provide it to
kernel.
--
Szymon K. Janc
[email protected]
Lets follow Android Lollipop behaviour and enable privacy on
startup.
---
android/bluetooth.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 4c359d0..54e3d97 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3423,6 +3423,32 @@ static void clear_auto_connect_list(void)
error("Could not clear auto connect list");
}
+static void set_privacy_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS)
+ error("Failed to set privacy mode: %s (0x%02x)",
+ mgmt_errstr(status), status);
+}
+
+static void set_privacy(void)
+{
+ struct mgmt_cp_set_privacy cp;
+
+ if (!local_irk_is_valid())
+ goto failed;
+
+ cp.privacy = 0x01;
+ memcpy(cp.irk, adapter.irk, sizeof(adapter.irk));
+
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_PRIVACY, adapter.index, sizeof(cp),
+ &cp, set_privacy_complete, NULL, NULL) > 0)
+ return;
+
+failed:
+ error("Could not set privacy mode");
+}
+
static void read_info_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -3497,6 +3523,9 @@ static void read_info_complete(uint8_t status, uint16_t length,
if (missing_settings & MGMT_SETTING_BONDABLE)
set_mode(MGMT_OP_SET_BONDABLE, 0x01);
+ if (missing_settings & MGMT_SETTING_PRIVACY)
+ set_privacy();
+
load_devices_info(cb);
load_devices_cache();
--
1.8.4
If IRK is not found it will be generated
---
android/bluetooth.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 410fa9d..4c359d0 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -39,6 +39,7 @@
#include "lib/sdp.h"
#include "lib/mgmt.h"
#include "lib/uuid.h"
+#include "src/shared/crypto.h"
#include "src/shared/util.h"
#include "src/shared/mgmt.h"
#include "src/shared/queue.h"
@@ -303,6 +304,22 @@ static void store_adapter_config(void)
g_key_file_free(key_file);
}
+static void generate_irk(void)
+{
+ struct bt_crypto *c;
+
+ c = bt_crypto_new();
+ if (!c) {
+ error("Could not create bt crypto and generate IRK");
+ return;
+ }
+
+ bt_crypto_random_bytes(c, adapter.irk, 16);
+ bt_crypto_unref(c);
+
+ store_adapter_config();
+}
+
static void load_adapter_config(void)
{
GError *gerr = NULL;
@@ -315,6 +332,7 @@ static void load_adapter_config(void)
str = g_key_file_get_string(key_file, "General", "Address", NULL);
if (!str) {
g_key_file_free(key_file);
+ generate_irk();
return;
}
@@ -330,6 +348,18 @@ static void load_adapter_config(void)
g_clear_error(&gerr);
}
+ str = g_key_file_get_string(key_file, "General", "IRK", NULL);
+ if (str) {
+ int i;
+
+ for (i = 0; i < 16; i++)
+ sscanf(str + (i * 2), "%02hhX", &adapter.irk[i]);
+
+ g_free(str);
+ } else {
+ generate_irk();
+ }
+
g_key_file_free(key_file);
}
--
1.8.4
---
android/bluetooth.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index e9c5be1..410fa9d 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -257,12 +257,21 @@ static void mgmt_debug(const char *str, void *user_data)
info("%s%s", prefix, str);
}
+static bool local_irk_is_valid(void)
+{
+ uint8_t empty_tab[16] = {0};
+
+ return memcmp(adapter.irk, empty_tab, 16);
+}
+
static void store_adapter_config(void)
{
GKeyFile *key_file;
gsize length = 0;
char addr[18];
char *data;
+ char key_str[33];
+ int i;
key_file = g_key_file_new();
@@ -279,6 +288,13 @@ static void store_adapter_config(void)
g_key_file_set_integer(key_file, "General", "DiscoverableTimeout",
adapter.discoverable_timeout);
+ if (local_irk_is_valid()) {
+ for (i = 0; i < 16; i++)
+ sprintf(key_str + (i * 2), "%2.2X", adapter.irk[i]);
+
+ g_key_file_set_string(key_file, "General", "IRK", key_str);
+ }
+
data = g_key_file_to_data(key_file, &length, NULL);
g_file_set_contents(SETTINGS_FILE, data, length, NULL);
--
1.8.4
---
android/bluetooth.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 48ca231..e9c5be1 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -176,6 +176,8 @@ static struct {
char *name;
+ uint8_t irk[16];
+
uint8_t max_advert_instance;
uint8_t rpa_offload_supported;
uint8_t max_irk_list_size;
@@ -196,6 +198,7 @@ static struct {
.index = MGMT_INDEX_NONE,
.dev_class = 0,
.name = NULL,
+ .irk = {0},
.max_advert_instance = 0,
.rpa_offload_supported = 0,
.max_irk_list_size = 0,
--
1.8.4