summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Łukasz Rymanowski <rlukasz@google.com> 2022-06-28 12:48:44 +0000
committer Łukasz Rymanowski <rlukasz@google.com> 2022-06-30 17:36:56 +0000
commit1cb0d9172cd16d6f5441ae1383b18f03aa8e4217 (patch)
tree0a78fdf0edc91794622b3674fad79f32df8e1dab
parentfb42ad05fdbc935869d780e68487a9dc1b1524b9 (diff)
eatt: Establish EATT after encryption is done.
As per specification EATT channel shall be encrypted and this patch makes this happen. However for some PTS test cases, we still would like to create L2CAP channels without encryption and this patch also allows to do that with flag PTS_ConnectEattUnencrypted Bug: 236944522 Test: PTS L2CAP/ECFC/BV-32-C Test: atest BluetoothInstrumentationTests Test: atest net_test_eatt Tag: #feature Change-Id: I98d7721f3733756e2c47bc7acd6f36d571b0eac0
-rw-r--r--system/conf/bt_stack.conf3
-rw-r--r--system/internal_include/stack_config.h1
-rw-r--r--system/main/stack_config.cc7
-rw-r--r--system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc3
-rw-r--r--system/profile/avrcp/tests/avrcp_device_test.cc3
-rw-r--r--system/stack/Android.bp1
-rw-r--r--system/stack/btm/btm_sec.cc6
-rw-r--r--system/stack/eatt/eatt_impl.h14
-rw-r--r--system/stack/gatt/gatt_main.cc6
-rw-r--r--system/stack/test/btm/stack_btm_test.cc3
-rw-r--r--system/stack/test/common/mock_btm_api_layer.cc10
-rw-r--r--system/stack/test/common/mock_btm_api_layer.h8
-rw-r--r--system/stack/test/eatt/eatt_test.cc64
-rw-r--r--system/stack/test/stack_smp_test.cc3
-rw-r--r--system/test/common/stack_config.cc3
15 files changed, 132 insertions, 3 deletions
diff --git a/system/conf/bt_stack.conf b/system/conf/bt_stack.conf
index 8a13213071..4111f16879 100644
--- a/system/conf/bt_stack.conf
+++ b/system/conf/bt_stack.conf
@@ -50,6 +50,9 @@ TRC_HID_DEV=2
# Start EATT without validation Server Supported Features
#PTS_ConnectEattUncondictionally=true
+# Start EATT on unecrypted link
+#PTS_ConnectEattUnencrypted=true
+
# Disable BR/EDR discovery after LE pairing to avoid cross key derivation errors
#PTS_DisableSDPOnLEPair=true
diff --git a/system/internal_include/stack_config.h b/system/internal_include/stack_config.h
index 4c13c54910..6ddbb94e87 100644
--- a/system/internal_include/stack_config.h
+++ b/system/internal_include/stack_config.h
@@ -35,6 +35,7 @@ typedef struct {
int (*get_pts_smp_failure_case)(void);
bool (*get_pts_force_eatt_for_notifications)(void);
bool (*get_pts_connect_eatt_unconditionally)(void);
+ bool (*get_pts_connect_eatt_before_encryption)(void);
config_t* (*get_all)(void);
} stack_config_t;
diff --git a/system/main/stack_config.cc b/system/main/stack_config.cc
index 50fbde2e74..f5d9f13d74 100644
--- a/system/main/stack_config.cc
+++ b/system/main/stack_config.cc
@@ -36,6 +36,7 @@ const char* PTS_SMP_FAILURE_CASE_KEY = "PTS_SmpFailureCase";
const char* PTS_FORCE_EATT_FOR_NOTIFICATIONS = "PTS_ForceEattForNotifications";
const char* PTS_CONNECT_EATT_UNCONDITIONALLY =
"PTS_ConnectEattUncondictionally";
+const char* PTS_CONNECT_EATT_UNENCRYPTED = "PTS_ConnectEattUnencrypted";
static std::unique_ptr<config_t> config;
} // namespace
@@ -123,6 +124,11 @@ static bool get_pts_connect_eatt_unconditionally(void) {
PTS_CONNECT_EATT_UNCONDITIONALLY, false);
}
+static bool get_pts_connect_eatt_before_encryption(void) {
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION,
+ PTS_CONNECT_EATT_UNENCRYPTED, false);
+}
+
static config_t* get_all(void) { return config.get(); }
const stack_config_t interface = {get_trace_config_enabled,
@@ -134,6 +140,7 @@ const stack_config_t interface = {get_trace_config_enabled,
get_pts_smp_failure_case,
get_pts_force_eatt_for_notifications,
get_pts_connect_eatt_unconditionally,
+ get_pts_connect_eatt_before_encryption,
get_all};
const stack_config_t* stack_config_get_interface(void) { return &interface; }
diff --git a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc
index b39bbdd9c5..e54f934c55 100644
--- a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc
+++ b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc
@@ -58,7 +58,8 @@ const stack_config_t interface = {nullptr, get_pts_avrcp_test,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
- nullptr, nullptr};
+ nullptr, nullptr,
+ nullptr};
void Callback(uint8_t, bool, std::unique_ptr<::bluetooth::PacketBuilder>) {}
diff --git a/system/profile/avrcp/tests/avrcp_device_test.cc b/system/profile/avrcp/tests/avrcp_device_test.cc
index f6c258be89..b21243ce36 100644
--- a/system/profile/avrcp/tests/avrcp_device_test.cc
+++ b/system/profile/avrcp/tests/avrcp_device_test.cc
@@ -54,7 +54,8 @@ const stack_config_t interface = {nullptr, get_pts_avrcp_test,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
- nullptr, nullptr};
+ nullptr, nullptr,
+ nullptr};
// TODO (apanicke): All the tests below are just basic positive unit tests.
// Add more tests to increase code coverage.
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index 3fc65b32e6..e98c6ff37d 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -832,6 +832,7 @@ cc_test {
"metrics/stack_metrics_logging.cc",
"test/btm/stack_btm_test.cc",
"test/btm/peer_packet_types_test.cc",
+ "test/common/mock_eatt.cc",
],
static_libs: [
"libbt-common",
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index 39c065dadd..756984dc93 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -46,6 +46,7 @@
#include "osi/include/osi.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/security_device_record.h"
+#include "stack/eatt/eatt.h"
#include "stack/include/acl_api.h"
#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/btm_status.h"
@@ -4730,6 +4731,11 @@ void btm_sec_dev_rec_cback_event(tBTM_SEC_DEV_REC* p_dev_rec,
}
btm_sec_check_pending_reqs();
+
+ if (btm_status == BTM_SUCCESS && is_le_transport) {
+ /* Link is encrypted, start EATT */
+ bluetooth::eatt::EattExtension::GetInstance()->Connect(p_dev_rec->bd_addr);
+ }
}
void btm_sec_cr_loc_oob_data_cback_event(const RawAddress& address,
diff --git a/system/stack/eatt/eatt_impl.h b/system/stack/eatt/eatt_impl.h
index 9a73f9b5a1..dfa641730b 100644
--- a/system/stack/eatt/eatt_impl.h
+++ b/system/stack/eatt/eatt_impl.h
@@ -116,6 +116,20 @@ struct eatt_impl {
void eatt_l2cap_connect_ind(const RawAddress& bda,
std::vector<uint16_t>& lcids, uint16_t psm,
uint16_t peer_mtu, uint8_t identifier) {
+ if (!stack_config_get_interface()
+ ->get_pts_connect_eatt_before_encryption() &&
+ !BTM_IsEncrypted(bda, BT_TRANSPORT_LE)) {
+ /* If Link is not encrypted, we shall not accept EATT channel creation. */
+ std::vector<uint16_t> empty;
+ uint16_t result = L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION;
+ if (BTM_IsLinkKeyKnown(bda, BT_TRANSPORT_LE)) {
+ result = L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP;
+ }
+ LOG_ERROR("ACL to device %s is unencrypted.", bda.ToString().c_str());
+ L2CA_ConnectCreditBasedRsp(bda, identifier, empty, result, nullptr);
+ return;
+ }
+
/* The assumption is that L2CAP layer already check parameters etc.
* Get our capabilities and accept all the channels.
*/
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index f2d0637b7a..1848a74d2a 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -27,6 +27,7 @@
#include "btif/include/btif_storage.h"
#include "connection_manager.h"
#include "device/include/interop.h"
+#include "internal_include/stack_config.h"
#include "l2c_api.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
@@ -497,7 +498,10 @@ static void gatt_le_connect_cback(uint16_t chan, const RawAddress& bd_addr,
}
}
- EattExtension::GetInstance()->Connect(bd_addr);
+ if (stack_config_get_interface()->get_pts_connect_eatt_before_encryption()) {
+ LOG_INFO(" Start EATT before encryption ");
+ EattExtension::GetInstance()->Connect(bd_addr);
+ }
}
/** This function is called to process the congestion callback from lcb */
diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc
index d685d2104e..98422a1f27 100644
--- a/system/stack/test/btm/stack_btm_test.cc
+++ b/system/stack/test/btm/stack_btm_test.cc
@@ -72,6 +72,7 @@ const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
int get_pts_smp_failure_case(void) { return 123; }
bool get_pts_force_eatt_for_notifications(void) { return false; }
bool get_pts_connect_eatt_unconditionally(void) { return false; }
+bool get_pts_connect_eatt_before_encryption(void) { return false; }
config_t* get_all(void) { return nullptr; }
const packet_fragmenter_t* packet_fragmenter_get_interface() { return nullptr; }
@@ -87,6 +88,8 @@ stack_config_t mock_stack_config{
get_pts_force_eatt_for_notifications,
.get_pts_connect_eatt_unconditionally =
get_pts_connect_eatt_unconditionally,
+ .get_pts_connect_eatt_before_encryption =
+ get_pts_connect_eatt_before_encryption,
.get_all = get_all,
};
const stack_config_t* stack_config_get_interface(void) {
diff --git a/system/stack/test/common/mock_btm_api_layer.cc b/system/stack/test/common/mock_btm_api_layer.cc
index 0b5c76fc8e..c1779c50ac 100644
--- a/system/stack/test/common/mock_btm_api_layer.cc
+++ b/system/stack/test/common/mock_btm_api_layer.cc
@@ -31,3 +31,13 @@ bool BTM_SetSecurityLevel(bool is_originator, const char* p_name,
sec_level, psm, mx_proto_id,
mx_chan_id);
}
+
+bool BTM_IsEncrypted(const RawAddress& remote_bd_addr,
+ tBT_TRANSPORT transport) {
+ return btm_api_interface->IsEncrypted(remote_bd_addr, transport);
+}
+
+bool BTM_IsLinkKeyKnown(const RawAddress& remote_bd_addr,
+ tBT_TRANSPORT transport) {
+ return btm_api_interface->IsLinkKeyKnown(remote_bd_addr, transport);
+}
diff --git a/system/stack/test/common/mock_btm_api_layer.h b/system/stack/test/common/mock_btm_api_layer.h
index 052babbafd..8c92fb30b5 100644
--- a/system/stack/test/common/mock_btm_api_layer.h
+++ b/system/stack/test/common/mock_btm_api_layer.h
@@ -32,6 +32,10 @@ class BtmApiInterface {
uint32_t mx_chan_id) = 0;
virtual uint8_t acl_link_role(const RawAddress& remote_bd_addr,
tBT_TRANSPORT transport) = 0;
+ virtual bool IsEncrypted(const RawAddress& remote_bd_addr,
+ tBT_TRANSPORT transport) = 0;
+ virtual bool IsLinkKeyKnown(const RawAddress& remote_bd_addr,
+ tBT_TRANSPORT transport) = 0;
virtual ~BtmApiInterface() = default;
};
@@ -43,6 +47,10 @@ class MockBtmApiInterface : public BtmApiInterface {
uint32_t mx_chan_id));
MOCK_METHOD2(acl_link_role, uint8_t(const RawAddress& remote_bd_addr,
tBT_TRANSPORT transport));
+ MOCK_METHOD2(IsEncrypted,
+ bool(const RawAddress& remote_bd_addr, tBT_TRANSPORT transport));
+ MOCK_METHOD2(IsLinkKeyKnown,
+ bool(const RawAddress& remote_bd_addr, tBT_TRANSPORT transport));
};
/**
diff --git a/system/stack/test/eatt/eatt_test.cc b/system/stack/test/eatt/eatt_test.cc
index 32c584810d..98d5a10d9e 100644
--- a/system/stack/test/eatt/eatt_test.cc
+++ b/system/stack/test/eatt/eatt_test.cc
@@ -185,6 +185,9 @@ TEST_F(EattTest, ConnectSucceed) {
TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) {
std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
+ ON_CALL(btm_api_interface_, IsEncrypted)
+ .WillByDefault(
+ [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
EXPECT_CALL(
l2cap_interface_,
ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
@@ -198,6 +201,9 @@ TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) {
TEST_F(EattTest, IncomingEattConnectionByKnownDevice) {
hci_role_ = HCI_ROLE_PERIPHERAL;
+ ON_CALL(btm_api_interface_, IsEncrypted)
+ .WillByDefault(
+ [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
.WillByDefault(
[](const RawAddress& addr,
@@ -224,11 +230,69 @@ TEST_F(EattTest, IncomingEattConnectionByKnownDevice) {
hci_role_ = HCI_ROLE_CENTRAL;
}
+TEST_F(EattTest, IncomingEattConnectionByKnownDeviceEncryptionOff) {
+ hci_role_ = HCI_ROLE_PERIPHERAL;
+ ON_CALL(btm_api_interface_, IsEncrypted)
+ .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
+ return false;
+ });
+ ON_CALL(btm_api_interface_, IsLinkKeyKnown)
+ .WillByDefault(
+ [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
+ ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
+ .WillByDefault(
+ [](const RawAddress& addr,
+ base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
+ std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
+ return true;
+ });
+ ON_CALL(gatt_interface_, GetEattSupport)
+ .WillByDefault([](const RawAddress& addr) { return true; });
+
+ eatt_instance_->Connect(test_address);
+ std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
+
+ EXPECT_CALL(l2cap_interface_,
+ ConnectCreditBasedRsp(test_address, 1, _,
+ L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP, _))
+ .WillOnce(Return(true));
+
+ l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
+ test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
+
+ hci_role_ = HCI_ROLE_CENTRAL;
+}
+
+TEST_F(EattTest, IncomingEattConnectionByUnknownDeviceEncryptionOff) {
+ std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
+
+ ON_CALL(btm_api_interface_, IsEncrypted)
+ .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
+ return false;
+ });
+ ON_CALL(btm_api_interface_, IsLinkKeyKnown)
+ .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
+ return false;
+ });
+ EXPECT_CALL(
+ l2cap_interface_,
+ ConnectCreditBasedRsp(test_address, 1, _,
+ L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION, _))
+ .WillOnce(Return(true));
+
+ l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
+ test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
+}
+
TEST_F(EattTest, ReconnectInitiatedByRemoteSucceed) {
ConnectDeviceEattSupported(1);
DisconnectEattDevice(connected_cids_);
std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
+ ON_CALL(btm_api_interface_, IsEncrypted)
+ .WillByDefault(
+ [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
+
EXPECT_CALL(
l2cap_interface_,
ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
diff --git a/system/stack/test/stack_smp_test.cc b/system/stack/test/stack_smp_test.cc
index 62fbd695ae..3180db65f3 100644
--- a/system/stack/test/stack_smp_test.cc
+++ b/system/stack/test/stack_smp_test.cc
@@ -47,6 +47,7 @@ const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
int get_pts_smp_failure_case(void) { return 123; }
bool get_pts_force_eatt_for_notifications(void) { return false; }
bool get_pts_connect_eatt_unconditionally(void) { return false; }
+bool get_pts_connect_eatt_before_encryption(void) { return false; }
config_t* get_all(void) { return nullptr; }
const packet_fragmenter_t* packet_fragmenter_get_interface() { return nullptr; }
@@ -62,6 +63,8 @@ stack_config_t mock_stack_config{
get_pts_force_eatt_for_notifications,
.get_pts_connect_eatt_unconditionally =
get_pts_connect_eatt_unconditionally,
+ .get_pts_connect_eatt_before_encryption =
+ get_pts_connect_eatt_before_encryption,
.get_all = get_all,
};
const stack_config_t* stack_config_get_interface(void) {
diff --git a/system/test/common/stack_config.cc b/system/test/common/stack_config.cc
index 211970762e..7bb25531c3 100644
--- a/system/test/common/stack_config.cc
+++ b/system/test/common/stack_config.cc
@@ -32,6 +32,7 @@ const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
int get_pts_smp_failure_case(void) { return 123; }
bool get_pts_force_eatt_for_notifications(void) { return false; }
bool get_pts_connect_eatt_unconditionally(void) { return false; }
+bool get_pts_connect_eatt_before_encryption(void) { return false; }
struct config_t;
config_t* get_all(void) { return nullptr; }
struct packet_fragmenter_t;
@@ -49,6 +50,8 @@ stack_config_t mock_stack_config{
get_pts_force_eatt_for_notifications,
.get_pts_connect_eatt_unconditionally =
get_pts_connect_eatt_unconditionally,
+ .get_pts_connect_eatt_before_encryption =
+ get_pts_connect_eatt_before_encryption,
.get_all = get_all,
};