#!/usr/bin/env python3 # # Copyright 2020 - The Android Open Source Project # # 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. import bluetooth_packets_python3 as bt_packets from bluetooth_packets_python3 import hci_packets from bluetooth_packets_python3 import l2cap_packets from bluetooth_packets_python3.l2cap_packets import CommandCode, LeCommandCode from cert.capture import Capture from cert.matchers import HciMatchers from cert.matchers import L2capMatchers from cert.matchers import SecurityMatchers from security.facade_pb2 import UiMsgType class HalCaptures(object): @staticmethod def ReadBdAddrCompleteCapture(): return Capture( lambda packet: packet.payload[0:5] == b'\x0e\x0a\x01\x09\x10', lambda packet: hci_packets.ReadBdAddrCompleteView( hci_packets.CommandCompleteView( hci_packets.EventView(bt_packets.PacketViewLittleEndian(list(packet.payload)))))) @staticmethod def ConnectionRequestCapture(): return Capture( lambda packet: packet.payload[0:2] == b'\x04\x0a', lambda packet: hci_packets.ConnectionRequestView( hci_packets.EventView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) @staticmethod def ConnectionCompleteCapture(): return Capture( lambda packet: packet.payload[0:3] == b'\x03\x0b\x00', lambda packet: hci_packets.ConnectionCompleteView( hci_packets.EventView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) @staticmethod def DisconnectionCompleteCapture(): return Capture( lambda packet: packet.payload[0:2] == b'\x05\x04', lambda packet: hci_packets.DisconnectionCompleteView( hci_packets.EventView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) @staticmethod def LeConnectionCompleteCapture(): return Capture( lambda packet: packet.payload[0] == 0x3e and (packet.payload[2] == 0x01 or packet.payload[2] == 0x0a), lambda packet: hci_packets.LeConnectionCompleteView( hci_packets.LeMetaEventView( hci_packets.EventView(bt_packets.PacketViewLittleEndian(list(packet.payload)))))) class HciCaptures(object): @staticmethod def ReadLocalOobDataCompleteCapture(): return Capture( HciMatchers.CommandComplete(hci_packets.OpCode.READ_LOCAL_OOB_DATA), lambda packet: HciMatchers.ExtractMatchingCommandComplete(packet.payload, hci_packets.OpCode.READ_LOCAL_OOB_DATA) ) @staticmethod def ReadLocalOobExtendedDataCompleteCapture(): return Capture( HciMatchers.CommandComplete(hci_packets.OpCode.READ_LOCAL_OOB_EXTENDED_DATA), lambda packet: HciMatchers.ExtractMatchingCommandComplete(packet.payload, hci_packets.OpCode.READ_LOCAL_OOB_EXTENDED_DATA) ) @staticmethod def ReadBdAddrCompleteCapture(): return Capture( HciMatchers.CommandComplete(hci_packets.OpCode.READ_BD_ADDR), lambda packet: hci_packets.ReadBdAddrCompleteView(HciMatchers.ExtractMatchingCommandComplete(packet.payload, hci_packets.OpCode.READ_BD_ADDR))) @staticmethod def ConnectionRequestCapture(): return Capture( HciMatchers.EventWithCode(hci_packets.EventCode.CONNECTION_REQUEST), lambda packet: hci_packets.ConnectionRequestView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.CONNECTION_REQUEST))) @staticmethod def ConnectionCompleteCapture(): return Capture( HciMatchers.EventWithCode(hci_packets.EventCode.CONNECTION_COMPLETE), lambda packet: hci_packets.ConnectionCompleteView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.CONNECTION_COMPLETE))) @staticmethod def DisconnectionCompleteCapture(): return Capture( HciMatchers.EventWithCode(hci_packets.EventCode.DISCONNECTION_COMPLETE), lambda packet: hci_packets.DisconnectionCompleteView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.DISCONNECTION_COMPLETE))) @staticmethod def LeConnectionCompleteCapture(): return Capture(HciMatchers.LeConnectionComplete(), lambda packet: HciMatchers.ExtractLeConnectionComplete(packet.payload)) @staticmethod def SimplePairingCompleteCapture(): return Capture(HciMatchers.EventWithCode(hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE), lambda packet: hci_packets.SimplePairingCompleteView( HciMatchers.ExtractEventWithCode(packet.payload, hci_packets.EventCode.SIMPLE_PAIRING_COMPLETE))) class L2capCaptures(object): @staticmethod def ConnectionRequest(psm): return Capture(L2capMatchers.ConnectionRequest(psm), L2capCaptures._extract_connection_request) @staticmethod def _extract_connection_request(packet): frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_REQUEST) return l2cap_packets.ConnectionRequestView(frame) @staticmethod def ConnectionResponse(scid): return Capture(L2capMatchers.ConnectionResponse(scid), L2capCaptures._extract_connection_response) @staticmethod def _extract_connection_response(packet): frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_RESPONSE) return l2cap_packets.ConnectionResponseView(frame) @staticmethod def ConfigurationRequest(cid=None): return Capture(L2capMatchers.ConfigurationRequest(cid), L2capCaptures._extract_configuration_request) @staticmethod def _extract_configuration_request(packet): frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONFIGURATION_REQUEST) return l2cap_packets.ConfigurationRequestView(frame) @staticmethod def CreditBasedConnectionRequest(psm): return Capture( L2capMatchers.CreditBasedConnectionRequest(psm), L2capCaptures._extract_credit_based_connection_request) @staticmethod def _extract_credit_based_connection_request(packet): frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_REQUEST) return l2cap_packets.LeCreditBasedConnectionRequestView(frame) @staticmethod def CreditBasedConnectionResponse(): return Capture(L2capMatchers.CreditBasedConnectionResponse(), L2capCaptures._extract_credit_based_connection_response) @staticmethod def _extract_credit_based_connection_response(packet): frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_RESPONSE) return l2cap_packets.LeCreditBasedConnectionResponseView(frame) @staticmethod def LinkSecurityInterfaceCallbackEvent(type): return Capture(L2capMatchers.LinkSecurityInterfaceCallbackEvent(type), L2capCaptures._extract_address) @staticmethod def _extract_address(packet): return packet.address class SecurityCaptures(object): @staticmethod def DisplayPasskey(): return Capture(SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY), SecurityCaptures._extract_passkey) @staticmethod def _extract_passkey(event): if event is None: return None return event.numeric_value