From 7927f68bb2d9b963288261e1e858463b43c52a2d Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Thu, 2 Jul 2015 16:14:28 -0700 Subject: [PATCH] Blacklist Nexus Remote for LE secure connections The Nexus remote will disconnect during encryption when paired with the secure connections feature enabled. This patch will blacklist the remote and mask out the feature during pairing. This patch introduces a new interop database with the aim of consolodating various blacklists and interop workarounds into a single database for code readability and maintainability of the list. Bug: 21817410 Change-Id: I6f510e1c8c6050ab4e313209122d028e12e5f54f --- device/Android.mk | 15 ++++++++--- device/include/interop.h | 36 +++++++++++++++++++++++++ device/include/interop_database.h | 33 +++++++++++++++++++++++ device/src/interop.c | 56 +++++++++++++++++++++++++++++++++++++++ device/test/interop_test.cpp | 36 +++++++++++++++++++++++++ stack/smp/smp_act.c | 25 ++++++++++++----- 6 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 device/include/interop.h create mode 100644 device/include/interop_database.h create mode 100644 device/src/interop.c create mode 100644 device/test/interop_test.cpp diff --git a/device/Android.mk b/device/Android.mk index 18b19dd1e..56d303f91 100644 --- a/device/Android.mk +++ b/device/Android.mk @@ -20,6 +20,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +# osi/include/atomic.h depends on gcc atomic functions +LOCAL_CLANG := false + LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/.. \ $(LOCAL_PATH)/include \ @@ -33,10 +36,10 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ src/classic/peer.c \ - src/controller.c + src/controller.c \ + src/interop.c -LOCAL_CFLAGS := $(bdroid_CFLAGS) -LOCAL_CONLYFLAGS := $(bdroid_CONLYFLAGS) +LOCAL_CFLAGS := -std=c99 $(bdroid_CFLAGS) LOCAL_MODULE := libbtdevice LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libc liblog @@ -48,6 +51,9 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) +# osi/include/atomic.h depends on gcc atomic functions +LOCAL_CLANG := false + LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/.. \ $(LOCAL_PATH)/../osi/include \ @@ -55,9 +61,10 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ ../osi/test/AllocationTestHarness.cpp \ + ./test/interop_test.cpp \ ./test/classic/peer_test.cpp -LOCAL_CFLAGS := -Wall -Werror $(bdroid_CFLAGS) +LOCAL_CFLAGS := -Wall -Werror -Werror=unused-variable LOCAL_MODULE := net_test_device LOCAL_MODULE_TAGS := tests LOCAL_SHARED_LIBRARIES := liblog libdl diff --git a/device/include/interop.h b/device/include/interop.h new file mode 100644 index 000000000..0a2a2dd47 --- /dev/null +++ b/device/include/interop.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#pragma once + +#include + +#include "btcore/include/bdaddr.h" + +typedef enum { + // Disable secure connections + // This is for pre BT 4.1/2 devices that do not handle secure mode + // very well. + INTEROP_DISABLE_LE_SECURE_CONNECTIONS +} interop_feature_t; + +// Check if a given |addr| matches a known interoperability workaround as identified +// by the |interop_feature_t| enum. This API is used for simple address based lookups +// where more information is not available. No look-ups or random address resolution +// is performed on |addr|. +bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr); diff --git a/device/include/interop_database.h b/device/include/interop_database.h new file mode 100644 index 000000000..64c13cf6c --- /dev/null +++ b/device/include/interop_database.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#pragma once + +#include "device/include/interop.h" + +typedef struct { + bt_bdaddr_t addr; + uint8_t len; + interop_feature_t feature; +} interop_entry_t; + +static const interop_entry_t interop_database[] = { + // Nexus Remote (Spike) + // Note: May affect other Asus brand devices + {{0x38, 0x2c, 0x4a, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS} +}; diff --git a/device/src/interop.c b/device/src/interop.c new file mode 100644 index 000000000..64dc24685 --- /dev/null +++ b/device/src/interop.c @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#define LOG_TAG "bt_device_interop" + +#include +#include // For memcmp + +#include "device/include/interop.h" +#include "device/include/interop_database.h" +#include "osi/include/log.h" + +#define CASE_RETURN_STR(const) case const: return #const; + +static const char* interop_feature_string(const interop_feature_t feature) { + switch (feature) { + CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS) + } + + return "UNKNOWN"; +} + +// Interface functions + +bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) { + assert(addr); + + const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t); + + for (size_t i = 0; i != db_size; ++i) { + if (feature == interop_database[i].feature && + memcmp(addr, &interop_database[i].addr, interop_database[i].len) == 0) { + char bdstr[20] = {0}; + LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__, + bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string(feature)); + return true; + } + } + + return false; +} diff --git a/device/test/interop_test.cpp b/device/test/interop_test.cpp new file mode 100644 index 000000000..3cf4e9e2c --- /dev/null +++ b/device/test/interop_test.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include + +extern "C" { +#include "device/include/interop.h" +} + +TEST(InteropTest, test_lookup_hit) { + bt_bdaddr_t test_address; + string_to_bdaddr("38:2c:4a:59:67:89", &test_address); + EXPECT_TRUE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address)); +} + +TEST(InteropTest, test_lookup_miss) { + bt_bdaddr_t test_address; + string_to_bdaddr("42:08:15:ae:ae:ae", &test_address); + EXPECT_FALSE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address)); +} + diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c index 4adde966d..92f240410 100644 --- a/stack/smp/smp_act.c +++ b/stack/smp/smp_act.c @@ -17,11 +17,12 @@ ******************************************************************************/ #include -#include "bt_target.h" -#include "bt_utils.h" -#include "btm_int.h" -#include "l2c_api.h" -#include "smp_int.h" +#include "device/include/interop.h" +#include "include/bt_target.h" +#include "stack/btm/btm_int.h" +#include "stack/include/l2c_api.h" +#include "stack/smp/smp_int.h" +#include "utils/include/bt_utils.h" #if SMP_INCLUDED == TRUE const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] = @@ -171,7 +172,9 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT; } - if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT)) + if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) + || interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, + (const bt_bdaddr_t *)&p_cb->pairing_bda)) { p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT; p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK; @@ -2022,10 +2025,18 @@ void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data SMP_TRACE_DEBUG("%s", __func__); if (!smp_calculate_link_key_from_long_term_key(p_cb)) { - SMP_TRACE_ERROR ("%s failed", __FUNCTION__); + SMP_TRACE_ERROR("%s failed", __FUNCTION__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); return; } + + if (interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, + (const bt_bdaddr_t *)&p_cb->pairing_bda)) + { + smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_LK, FALSE); + SMP_TRACE_DEBUG("%s successfully completed", __FUNCTION__); + smp_key_distribution(p_cb, NULL); + } } /******************************************************************************* -- 2.11.0