Loading system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc +127 −2 Original line number Diff line number Diff line Loading @@ -285,6 +285,12 @@ void LinkLayerController::IncomingPacket( case (model::packets::PacketType::PASSKEY_FAILED): IncomingPasskeyFailedPacket(incoming); break; case (model::packets::PacketType::PIN_REQUEST): IncomingPinRequestPacket(incoming); break; case (model::packets::PacketType::PIN_RESPONSE): IncomingPinResponsePacket(incoming); break; case (model::packets::PacketType::REMOTE_NAME_REQUEST): IncomingRemoteNameRequest(incoming); break; Loading Loading @@ -1339,6 +1345,111 @@ void LinkLayerController::IncomingPasskeyFailedPacket( }); } void LinkLayerController::IncomingPinRequestPacket( model::packets::LinkLayerPacketView incoming) { auto request = model::packets::PinRequestView::Create(incoming); ASSERT(request.IsValid()); auto peer = incoming.GetSourceAddress(); auto handle = connections_.GetHandle(AddressWithType( peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS)); if (handle == kReservedHandle) { LOG_INFO("Dropping %s request (no connection)", peer.ToString().c_str()); auto wrong_pin = request.GetPinCode(); wrong_pin[0] = wrong_pin[0]++; SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, wrong_pin)); return; } if (security_manager_.AuthenticationInProgress()) { auto current_peer = security_manager_.GetAuthenticationAddress(); if (current_peer != peer) { LOG_INFO("Dropping %s request (%s in progress)", peer.ToString().c_str(), current_peer.ToString().c_str()); auto wrong_pin = request.GetPinCode(); wrong_pin[0] = wrong_pin[0]++; SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, wrong_pin)); return; } } else { LOG_INFO("Incoming authentication request %s", peer.ToString().c_str()); security_manager_.AuthenticationRequest(peer, handle); } auto current_peer = security_manager_.GetAuthenticationAddress(); security_manager_.SetRemotePin(peer, request.GetPinCode()); if (security_manager_.GetPinRequested(peer)) { if (security_manager_.GetLocalPinResponseReceived(peer)) { SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, request.GetPinCode())); if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } } else { LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str()); ScheduleTask(milliseconds(5), [this, peer]() { security_manager_.SetPinRequested(peer); send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer)); }); } } void LinkLayerController::IncomingPinResponsePacket( model::packets::LinkLayerPacketView incoming) { auto request = model::packets::PinResponseView::Create(incoming); ASSERT(request.IsValid()); auto peer = incoming.GetSourceAddress(); auto handle = connections_.GetHandle(AddressWithType( peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS)); if (handle == kReservedHandle) { LOG_INFO("Dropping %s request (no connection)", peer.ToString().c_str()); return; } if (security_manager_.AuthenticationInProgress()) { auto current_peer = security_manager_.GetAuthenticationAddress(); if (current_peer != peer) { LOG_INFO("Dropping %s request (%s in progress)", peer.ToString().c_str(), current_peer.ToString().c_str()); return; } } else { LOG_INFO("Dropping response without authentication request %s", peer.ToString().c_str()); return; } auto current_peer = security_manager_.GetAuthenticationAddress(); security_manager_.SetRemotePin(peer, request.GetPinCode()); if (security_manager_.GetPinRequested(peer)) { if (security_manager_.GetLocalPinResponseReceived(peer)) { SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, request.GetPinCode())); if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } } else { LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str()); ScheduleTask(milliseconds(5), [this, peer]() { security_manager_.SetPinRequested(peer); send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer)); }); } } void LinkLayerController::IncomingPagePacket( model::packets::LinkLayerPacketView incoming) { auto page = model::packets::PageView::Create(incoming); Loading Loading @@ -1677,8 +1788,22 @@ ErrorCode LinkLayerController::PinCodeRequestReply(const Address& peer, LOG_INFO("No Pin Requested for %s", peer.ToString().c_str()); return ErrorCode::COMMAND_DISALLOWED; } security_manager_.SetLocalPin(peer, pin); if (security_manager_.GetRemotePinResponseReceived(peer)) { if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } else { SendLinkLayerPacket(model::packets::PinRequestBuilder::Create( properties_.GetAddress(), peer, pin)); } return ErrorCode::SUCCESS; } Loading system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h +2 −0 Original line number Diff line number Diff line Loading @@ -369,6 +369,8 @@ class LinkLayerController { void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet); void IncomingPasskeyPacket(model::packets::LinkLayerPacketView packet); void IncomingPasskeyFailedPacket(model::packets::LinkLayerPacketView packet); void IncomingPinRequestPacket(model::packets::LinkLayerPacketView packet); void IncomingPinResponsePacket(model::packets::LinkLayerPacketView packet); void IncomingReadRemoteLmpFeatures( model::packets::LinkLayerPacketView packet); void IncomingReadRemoteLmpFeaturesResponse( Loading system/vendor_libs/test_vendor_lib/model/controller/security_manager.cc +25 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ void SecurityManager::AuthenticationRequest(const Address& addr, uint16_t handle current_handle_ = handle; peer_address_ = addr; peer_pin_requested_ = false; peer_pin_received_ = false; host_pin_received_ = false; } void SecurityManager::AuthenticationRequestFinished() { Loading Loading @@ -198,4 +200,27 @@ bool SecurityManager::GetPinRequested(const Address& addr) { return peer_pin_requested_; } void SecurityManager::SetLocalPin(const Address& peer, const std::vector<uint8_t>& pin) { host_pin_received_ = true; host_pin_ = pin; } void SecurityManager::SetRemotePin(const Address& peer, const std::vector<uint8_t>& pin) { peer_pin_received_ = true; peer_pin_ = pin; } bool SecurityManager::GetLocalPinResponseReceived(const Address& peer) { return host_pin_received_; } bool SecurityManager::GetRemotePinResponseReceived(const Address& peer) { return peer_pin_received_; } bool SecurityManager::PinCompare() { return host_pin_received_ && peer_pin_received_ && peer_pin_ == host_pin_; } } // namespace test_vendor_lib system/vendor_libs/test_vendor_lib/model/controller/security_manager.h +10 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <cstdint> #include <string> #include <unordered_map> #include <vector> #include "hci/address.h" Loading Loading @@ -80,6 +81,11 @@ class SecurityManager { void SetPinRequested(const Address& addr); bool GetPinRequested(const Address& addr); void SetLocalPin(const Address& peer, const std::vector<uint8_t>& pin); void SetRemotePin(const Address& peer, const std::vector<uint8_t>& pin); bool GetLocalPinResponseReceived(const Address& peer); bool GetRemotePinResponseReceived(const Address& peer); bool PinCompare(); void SetPeerIoCapability(const Address& addr, uint8_t io_capability, uint8_t oob_present_flag, uint8_t authentication_requirements); Loading @@ -100,12 +106,16 @@ class SecurityManager { AuthenticationType peer_authentication_requirements_{ AuthenticationType::NO_BONDING}; bool peer_pin_requested_{false}; bool peer_pin_received_{false}; std::vector<uint8_t> peer_pin_; bool host_capabilities_valid_{false}; IoCapabilityType host_io_capability_{IoCapabilityType::DISPLAY_ONLY}; uint8_t host_oob_present_flag_{0}; AuthenticationType host_authentication_requirements_{ AuthenticationType::NO_BONDING}; std::vector<uint8_t> host_pin_; bool host_pin_received_{false}; bool authenticating_{false}; uint16_t current_handle_{}; Loading system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl +14 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ enum PacketType : 8 { PASSKEY = 0x27, PASSKEY_FAILED = 0x28, KEYPRESS_NOTIFICATION = 0x29, PIN_REQUEST = 0x2A, PIN_RESPONSE = 0x2B, } packet LinkLayerPacket { Loading Loading @@ -336,3 +338,15 @@ packet PasskeyFailed : LinkLayerPacket (type = PASSKEY_FAILED){ packet KeypressNotification : LinkLayerPacket (type = KEYPRESS_NOTIFICATION){ notification_type : PasskeyNotificationType, } packet PinRequest : LinkLayerPacket (type = PIN_REQUEST) { _size_(pin_code) : 5, // 0x01 - 0x10 _reserved_ : 3, pin_code : 8[], // string parameter, first octet first } packet PinResponse : LinkLayerPacket (type = PIN_RESPONSE) { _size_(pin_code) : 5, // 0x01 - 0x10 _reserved_ : 3, pin_code : 8[], // string parameter, first octet first } Loading
system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc +127 −2 Original line number Diff line number Diff line Loading @@ -285,6 +285,12 @@ void LinkLayerController::IncomingPacket( case (model::packets::PacketType::PASSKEY_FAILED): IncomingPasskeyFailedPacket(incoming); break; case (model::packets::PacketType::PIN_REQUEST): IncomingPinRequestPacket(incoming); break; case (model::packets::PacketType::PIN_RESPONSE): IncomingPinResponsePacket(incoming); break; case (model::packets::PacketType::REMOTE_NAME_REQUEST): IncomingRemoteNameRequest(incoming); break; Loading Loading @@ -1339,6 +1345,111 @@ void LinkLayerController::IncomingPasskeyFailedPacket( }); } void LinkLayerController::IncomingPinRequestPacket( model::packets::LinkLayerPacketView incoming) { auto request = model::packets::PinRequestView::Create(incoming); ASSERT(request.IsValid()); auto peer = incoming.GetSourceAddress(); auto handle = connections_.GetHandle(AddressWithType( peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS)); if (handle == kReservedHandle) { LOG_INFO("Dropping %s request (no connection)", peer.ToString().c_str()); auto wrong_pin = request.GetPinCode(); wrong_pin[0] = wrong_pin[0]++; SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, wrong_pin)); return; } if (security_manager_.AuthenticationInProgress()) { auto current_peer = security_manager_.GetAuthenticationAddress(); if (current_peer != peer) { LOG_INFO("Dropping %s request (%s in progress)", peer.ToString().c_str(), current_peer.ToString().c_str()); auto wrong_pin = request.GetPinCode(); wrong_pin[0] = wrong_pin[0]++; SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, wrong_pin)); return; } } else { LOG_INFO("Incoming authentication request %s", peer.ToString().c_str()); security_manager_.AuthenticationRequest(peer, handle); } auto current_peer = security_manager_.GetAuthenticationAddress(); security_manager_.SetRemotePin(peer, request.GetPinCode()); if (security_manager_.GetPinRequested(peer)) { if (security_manager_.GetLocalPinResponseReceived(peer)) { SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, request.GetPinCode())); if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } } else { LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str()); ScheduleTask(milliseconds(5), [this, peer]() { security_manager_.SetPinRequested(peer); send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer)); }); } } void LinkLayerController::IncomingPinResponsePacket( model::packets::LinkLayerPacketView incoming) { auto request = model::packets::PinResponseView::Create(incoming); ASSERT(request.IsValid()); auto peer = incoming.GetSourceAddress(); auto handle = connections_.GetHandle(AddressWithType( peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS)); if (handle == kReservedHandle) { LOG_INFO("Dropping %s request (no connection)", peer.ToString().c_str()); return; } if (security_manager_.AuthenticationInProgress()) { auto current_peer = security_manager_.GetAuthenticationAddress(); if (current_peer != peer) { LOG_INFO("Dropping %s request (%s in progress)", peer.ToString().c_str(), current_peer.ToString().c_str()); return; } } else { LOG_INFO("Dropping response without authentication request %s", peer.ToString().c_str()); return; } auto current_peer = security_manager_.GetAuthenticationAddress(); security_manager_.SetRemotePin(peer, request.GetPinCode()); if (security_manager_.GetPinRequested(peer)) { if (security_manager_.GetLocalPinResponseReceived(peer)) { SendLinkLayerPacket(model::packets::PinResponseBuilder::Create( properties_.GetAddress(), peer, request.GetPinCode())); if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } } else { LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str()); ScheduleTask(milliseconds(5), [this, peer]() { security_manager_.SetPinRequested(peer); send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer)); }); } } void LinkLayerController::IncomingPagePacket( model::packets::LinkLayerPacketView incoming) { auto page = model::packets::PageView::Create(incoming); Loading Loading @@ -1677,8 +1788,22 @@ ErrorCode LinkLayerController::PinCodeRequestReply(const Address& peer, LOG_INFO("No Pin Requested for %s", peer.ToString().c_str()); return ErrorCode::COMMAND_DISALLOWED; } security_manager_.SetLocalPin(peer, pin); if (security_manager_.GetRemotePinResponseReceived(peer)) { if (security_manager_.PinCompare()) { LOG_INFO("Authenticating %s", peer.ToString().c_str()); SaveKeyAndAuthenticate('L', peer); // Legacy } else { security_manager_.AuthenticationRequestFinished(); ScheduleTask(milliseconds(5), [this, peer]() { send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create( ErrorCode::AUTHENTICATION_FAILURE, peer)); }); } } else { SendLinkLayerPacket(model::packets::PinRequestBuilder::Create( properties_.GetAddress(), peer, pin)); } return ErrorCode::SUCCESS; } Loading
system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h +2 −0 Original line number Diff line number Diff line Loading @@ -369,6 +369,8 @@ class LinkLayerController { void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet); void IncomingPasskeyPacket(model::packets::LinkLayerPacketView packet); void IncomingPasskeyFailedPacket(model::packets::LinkLayerPacketView packet); void IncomingPinRequestPacket(model::packets::LinkLayerPacketView packet); void IncomingPinResponsePacket(model::packets::LinkLayerPacketView packet); void IncomingReadRemoteLmpFeatures( model::packets::LinkLayerPacketView packet); void IncomingReadRemoteLmpFeaturesResponse( Loading
system/vendor_libs/test_vendor_lib/model/controller/security_manager.cc +25 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ void SecurityManager::AuthenticationRequest(const Address& addr, uint16_t handle current_handle_ = handle; peer_address_ = addr; peer_pin_requested_ = false; peer_pin_received_ = false; host_pin_received_ = false; } void SecurityManager::AuthenticationRequestFinished() { Loading Loading @@ -198,4 +200,27 @@ bool SecurityManager::GetPinRequested(const Address& addr) { return peer_pin_requested_; } void SecurityManager::SetLocalPin(const Address& peer, const std::vector<uint8_t>& pin) { host_pin_received_ = true; host_pin_ = pin; } void SecurityManager::SetRemotePin(const Address& peer, const std::vector<uint8_t>& pin) { peer_pin_received_ = true; peer_pin_ = pin; } bool SecurityManager::GetLocalPinResponseReceived(const Address& peer) { return host_pin_received_; } bool SecurityManager::GetRemotePinResponseReceived(const Address& peer) { return peer_pin_received_; } bool SecurityManager::PinCompare() { return host_pin_received_ && peer_pin_received_ && peer_pin_ == host_pin_; } } // namespace test_vendor_lib
system/vendor_libs/test_vendor_lib/model/controller/security_manager.h +10 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <cstdint> #include <string> #include <unordered_map> #include <vector> #include "hci/address.h" Loading Loading @@ -80,6 +81,11 @@ class SecurityManager { void SetPinRequested(const Address& addr); bool GetPinRequested(const Address& addr); void SetLocalPin(const Address& peer, const std::vector<uint8_t>& pin); void SetRemotePin(const Address& peer, const std::vector<uint8_t>& pin); bool GetLocalPinResponseReceived(const Address& peer); bool GetRemotePinResponseReceived(const Address& peer); bool PinCompare(); void SetPeerIoCapability(const Address& addr, uint8_t io_capability, uint8_t oob_present_flag, uint8_t authentication_requirements); Loading @@ -100,12 +106,16 @@ class SecurityManager { AuthenticationType peer_authentication_requirements_{ AuthenticationType::NO_BONDING}; bool peer_pin_requested_{false}; bool peer_pin_received_{false}; std::vector<uint8_t> peer_pin_; bool host_capabilities_valid_{false}; IoCapabilityType host_io_capability_{IoCapabilityType::DISPLAY_ONLY}; uint8_t host_oob_present_flag_{0}; AuthenticationType host_authentication_requirements_{ AuthenticationType::NO_BONDING}; std::vector<uint8_t> host_pin_; bool host_pin_received_{false}; bool authenticating_{false}; uint16_t current_handle_{}; Loading
system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl +14 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ enum PacketType : 8 { PASSKEY = 0x27, PASSKEY_FAILED = 0x28, KEYPRESS_NOTIFICATION = 0x29, PIN_REQUEST = 0x2A, PIN_RESPONSE = 0x2B, } packet LinkLayerPacket { Loading Loading @@ -336,3 +338,15 @@ packet PasskeyFailed : LinkLayerPacket (type = PASSKEY_FAILED){ packet KeypressNotification : LinkLayerPacket (type = KEYPRESS_NOTIFICATION){ notification_type : PasskeyNotificationType, } packet PinRequest : LinkLayerPacket (type = PIN_REQUEST) { _size_(pin_code) : 5, // 0x01 - 0x10 _reserved_ : 3, pin_code : 8[], // string parameter, first octet first } packet PinResponse : LinkLayerPacket (type = PIN_RESPONSE) { _size_(pin_code) : 5, // 0x01 - 0x10 _reserved_ : 3, pin_code : 8[], // string parameter, first octet first }