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