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 l2cap_packets 19from bluetooth_packets_python3.l2cap_packets import CommandCode, LeCommandCode 20from blueberry.tests.gd.cert.capture import Capture 21from blueberry.tests.gd.cert.matchers import HciMatchers 22from blueberry.tests.gd.cert.matchers import L2capMatchers 23from blueberry.tests.gd.cert.matchers import SecurityMatchers 24from blueberry.facade.security.facade_pb2 import UiMsgType 25import hci_packets as hci 26 27 28class HalCaptures(object): 29 30 @staticmethod 31 def ReadBdAddrCompleteCapture(): 32 return Capture(lambda packet: packet.payload[0:5] == b'\x0e\x0a\x01\x09\x10', 33 lambda packet: hci.Event.parse_all(packet.payload)) 34 35 @staticmethod 36 def ConnectionRequestCapture(): 37 return Capture(lambda packet: packet.payload[0:2] == b'\x04\x0a', 38 lambda packet: hci.Event.parse_all(packet.payload)) 39 40 @staticmethod 41 def ConnectionCompleteCapture(): 42 return Capture(lambda packet: packet.payload[0:3] == b'\x03\x0b\x00', 43 lambda packet: hci.Event.parse_all(packet.payload)) 44 45 @staticmethod 46 def DisconnectionCompleteCapture(): 47 return Capture(lambda packet: packet.payload[0:2] == b'\x05\x04', 48 lambda packet: hci.Event.parse_all(packet.payload)) 49 50 @staticmethod 51 def LeConnectionCompleteCapture(): 52 return Capture( 53 lambda packet: packet.payload[0] == 0x3e and (packet.payload[2] == 0x01 or packet.payload[2] == 0x0a), 54 lambda packet: hci.Event.parse_all(packet.payload)) 55 56 57class HciCaptures(object): 58 59 @staticmethod 60 def ReadLocalOobDataCompleteCapture(): 61 return Capture( 62 HciMatchers.CommandComplete(hci.OpCode.READ_LOCAL_OOB_DATA), 63 lambda packet: HciMatchers.ExtractMatchingCommandComplete(packet.payload, hci.OpCode.READ_LOCAL_OOB_DATA)) 64 65 @staticmethod 66 def ReadLocalOobExtendedDataCompleteCapture(): 67 return Capture( 68 HciMatchers.CommandComplete(hci.OpCode.READ_LOCAL_OOB_EXTENDED_DATA), lambda packet: HciMatchers. 69 ExtractMatchingCommandComplete(packet.payload, hci.OpCode.READ_LOCAL_OOB_EXTENDED_DATA)) 70 71 @staticmethod 72 def ReadBdAddrCompleteCapture(): 73 return Capture(HciMatchers.CommandComplete(hci.OpCode.READ_BD_ADDR), 74 lambda packet: hci.Event.parse_all(packet.payload)) 75 76 @staticmethod 77 def ConnectionRequestCapture(): 78 return Capture(HciMatchers.EventWithCode(hci.EventCode.CONNECTION_REQUEST), 79 lambda packet: hci.Event.parse_all(packet.payload)) 80 81 @staticmethod 82 def ConnectionCompleteCapture(): 83 return Capture(HciMatchers.EventWithCode(hci.EventCode.CONNECTION_COMPLETE), 84 lambda packet: hci.Event.parse_all(packet.payload)) 85 86 @staticmethod 87 def DisconnectionCompleteCapture(): 88 return Capture(HciMatchers.EventWithCode(hci.EventCode.DISCONNECTION_COMPLETE), 89 lambda packet: hci.Event.parse_all(packet.payload)) 90 91 @staticmethod 92 def LeConnectionCompleteCapture(): 93 return Capture(HciMatchers.LeConnectionComplete(), 94 lambda packet: HciMatchers.ExtractLeConnectionComplete(packet.payload)) 95 96 @staticmethod 97 def SimplePairingCompleteCapture(): 98 return Capture(HciMatchers.EventWithCode(hci.EventCode.SIMPLE_PAIRING_COMPLETE), 99 lambda packet: hci.Event.parse_all(packet.payload)) 100 101 102class L2capCaptures(object): 103 104 @staticmethod 105 def ConnectionRequest(psm): 106 return Capture(L2capMatchers.ConnectionRequest(psm), L2capCaptures._extract_connection_request) 107 108 @staticmethod 109 def _extract_connection_request(packet): 110 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_REQUEST) 111 return l2cap_packets.ConnectionRequestView(frame) 112 113 @staticmethod 114 def ConnectionResponse(scid): 115 return Capture(L2capMatchers.ConnectionResponse(scid), L2capCaptures._extract_connection_response) 116 117 @staticmethod 118 def _extract_connection_response(packet): 119 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONNECTION_RESPONSE) 120 return l2cap_packets.ConnectionResponseView(frame) 121 122 @staticmethod 123 def ConfigurationRequest(cid=None): 124 return Capture(L2capMatchers.ConfigurationRequest(cid), L2capCaptures._extract_configuration_request) 125 126 @staticmethod 127 def _extract_configuration_request(packet): 128 frame = L2capMatchers.control_frame_with_code(packet, CommandCode.CONFIGURATION_REQUEST) 129 return l2cap_packets.ConfigurationRequestView(frame) 130 131 @staticmethod 132 def CreditBasedConnectionRequest(psm): 133 return Capture(L2capMatchers.CreditBasedConnectionRequest(psm), 134 L2capCaptures._extract_credit_based_connection_request) 135 136 @staticmethod 137 def _extract_credit_based_connection_request(packet): 138 frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_REQUEST) 139 return l2cap_packets.LeCreditBasedConnectionRequestView(frame) 140 141 @staticmethod 142 def CreditBasedConnectionResponse(): 143 return Capture(L2capMatchers.CreditBasedConnectionResponse(), 144 L2capCaptures._extract_credit_based_connection_response) 145 146 @staticmethod 147 def _extract_credit_based_connection_response(packet): 148 frame = L2capMatchers.le_control_frame_with_code(packet, LeCommandCode.LE_CREDIT_BASED_CONNECTION_RESPONSE) 149 return l2cap_packets.LeCreditBasedConnectionResponseView(frame) 150 151 @staticmethod 152 def LinkSecurityInterfaceCallbackEvent(type): 153 return Capture(L2capMatchers.LinkSecurityInterfaceCallbackEvent(type), L2capCaptures._extract_address) 154 155 @staticmethod 156 def _extract_address(packet): 157 return packet.address 158 159 160class SecurityCaptures(object): 161 162 @staticmethod 163 def DisplayPasskey(): 164 return Capture(SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY), SecurityCaptures._extract_passkey) 165 166 @staticmethod 167 def _extract_passkey(event): 168 if event is None: 169 return None 170 return event.numeric_value 171