1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import bluetooth_packets_python3 as bt_packets 18from bluetooth_packets_python3 import hci_packets 19from bluetooth_packets_python3 import l2cap_packets 20from bluetooth_packets_python3.l2cap_packets import CommandCode, LeCommandCode 21from cert.capture import Capture 22from cert.matchers import L2capMatchers 23from cert.matchers import SecurityMatchers 24from security.facade_pb2 import UiMsgType 25 26 27class HalCaptures(object): 28 29 @staticmethod 30 def ReadBdAddrCompleteCapture(): 31 return Capture( 32 lambda packet: packet.payload[0:5] == b'\x0e\x0a\x01\x09\x10', lambda packet: hci_packets.ReadBdAddrCompleteView( 33 hci_packets.CommandCompleteView( 34 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.payload)))))) 35 36 @staticmethod 37 def ConnectionRequestCapture(): 38 return Capture( 39 lambda packet: packet.payload[0:2] == b'\x04\x0a', lambda packet: hci_packets.ConnectionRequestView( 40 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) 41 42 @staticmethod 43 def ConnectionCompleteCapture(): 44 return Capture( 45 lambda packet: packet.payload[0:3] == b'\x03\x0b\x00', lambda packet: hci_packets.ConnectionCompleteView( 46 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) 47 48 @staticmethod 49 def DisconnectionCompleteCapture(): 50 return Capture( 51 lambda packet: packet.payload[0:2] == b'\x05\x04', lambda packet: hci_packets.DisconnectionCompleteView( 52 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.payload))))) 53 54 @staticmethod 55 def LeConnectionCompleteCapture(): 56 return Capture( 57 lambda packet: packet.payload[0] == 0x3e and (packet.payload[2] == 0x01 or packet.payload[2] == 0x0a), 58 lambda packet: hci_packets.LeConnectionCompleteView( 59 hci_packets.LeMetaEventView( 60 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.payload)))))) 61 62 63class HciCaptures(object): 64 65 @staticmethod 66 def ReadBdAddrCompleteCapture(): 67 return Capture( 68 lambda packet: packet.event[0:5] == b'\x0e\x0a\x01\x09\x10', lambda packet: hci_packets.ReadBdAddrCompleteView( 69 hci_packets.CommandCompleteView( 70 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.event)))))) 71 72 @staticmethod 73 def ConnectionRequestCapture(): 74 return Capture( 75 lambda packet: packet.event[0:2] == b'\x04\x0a', lambda packet: hci_packets.ConnectionRequestView( 76 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.event))))) 77 78 @staticmethod 79 def ConnectionCompleteCapture(): 80 return Capture( 81 lambda packet: packet.event[0:3] == b'\x03\x0b\x00', lambda packet: hci_packets.ConnectionCompleteView( 82 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.event))))) 83 84 @staticmethod 85 def DisconnectionCompleteCapture(): 86 return Capture( 87 lambda packet: packet.event[0:2] == b'\x05\x04', lambda packet: hci_packets.DisconnectionCompleteView( 88 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.event))))) 89 90 @staticmethod 91 def LeConnectionCompleteCapture(): 92 return Capture( 93 lambda packet: packet.event[0] == 0x3e and (packet.event[2] == 0x01 or packet.event[2] == 0x0a), 94 lambda packet: hci_packets.LeConnectionCompleteView( 95 hci_packets.LeMetaEventView( 96 hci_packets.EventPacketView(bt_packets.PacketViewLittleEndian(list(packet.event)))))) 97 98 99class L2capCaptures(object): 100 101 @staticmethod 102 def ConnectionRequest(psm): 103 return Capture(L2capMatchers.ConnectionRequest(psm), L2capCaptures._extract_connection_request) 104 105 @staticmethod 106 def _extract_connection_request(packet): 107 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_REQUEST) 108 return l2cap_packets.ConnectionRequestView(frame) 109 110 @staticmethod 111 def ConnectionResponse(scid): 112 return Capture(L2capMatchers.ConnectionResponse(scid), L2capCaptures._extract_connection_response) 113 114 @staticmethod 115 def _extract_connection_response(packet): 116 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_RESPONSE) 117 return l2cap_packets.ConnectionResponseView(frame) 118 119 @staticmethod 120 def ConfigurationRequest(cid=None): 121 return Capture(L2capMatchers.ConfigurationRequest(cid), L2capCaptures._extract_configuration_request) 122 123 @staticmethod 124 def _extract_configuration_request(packet): 125 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONFIGURATION_REQUEST) 126 return l2cap_packets.ConfigurationRequestView(frame) 127 128 @staticmethod 129 def CreditBasedConnectionRequest(psm): 130 return Capture( 131 L2capMatchers.CreditBasedConnectionRequest(psm), L2capCaptures._extract_credit_based_connection_request) 132 133 @staticmethod 134 def _extract_credit_based_connection_request(packet): 135 frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_REQUEST) 136 return l2cap_packets.LeCreditBasedConnectionRequestView(frame) 137 138 @staticmethod 139 def CreditBasedConnectionResponse(): 140 return Capture(L2capMatchers.CreditBasedConnectionResponse(), 141 L2capCaptures._extract_credit_based_connection_response) 142 143 @staticmethod 144 def _extract_credit_based_connection_response(packet): 145 frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_RESPONSE) 146 return l2cap_packets.LeCreditBasedConnectionResponseView(frame) 147 148 149class SecurityCaptures(object): 150 151 @staticmethod 152 def DisplayPasskey(): 153 return Capture(SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY), SecurityCaptures._extract_passkey) 154 155 @staticmethod 156 def _extract_passkey(event): 157 if event is None: 158 return None 159 return event.numeric_value 160