Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bluetooth: Add some EIR fields #4273

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions scapy/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -3171,7 +3171,8 @@ def __init__(self,
name, # type: str
default, # type: Optional[Union[int, FlagValue]]
size, # type: int
names # type: Union[List[str], str, Dict[int, str]]
names, # type: Union[List[str], str, Dict[int, str]]
**kwargs # type: Any
):
# type: (...) -> None
# Convert the dict to a list
Expand All @@ -3182,7 +3183,7 @@ def __init__(self,
names = tmp
# Store the names as str or list
self.names = names
super(FlagsField, self).__init__(name, default, size)
super(FlagsField, self).__init__(name, default, size, **kwargs)

def _fixup_val(self, x):
# type: (Any) -> Optional[FlagValue]
Expand Down
111 changes: 111 additions & 0 deletions scapy/layers/bluetooth.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
XLELongField,
XStrLenField,
XLEShortField,
XLEIntField,
LEMACField,
BitEnumField,
)
from scapy.supersocket import SuperSocket
from scapy.sendrecv import sndrcv
Expand Down Expand Up @@ -1038,6 +1040,19 @@ class EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):
name = "Incomplete list of 16-bit service UUIDs"


class EIR_CompleteList32BitServiceUUIDs(EIR_Element):
name = 'Complete list of 32-bit service UUIDs'
fields_desc = [
# https://www.bluetooth.com/specifications/assigned-numbers
FieldListField('svc_uuids', None, XLEIntField('uuid', 0),
length_from=EIR_Element.length_from)
]


class EIR_IncompleteList32BitServiceUUIDs(EIR_CompleteList32BitServiceUUIDs):
name = 'Incomplete list of 32-bit service UUIDs'


class EIR_CompleteList128BitServiceUUIDs(EIR_Element):
name = "Complete list of 128-bit service UUIDs"
fields_desc = [
Expand Down Expand Up @@ -1067,6 +1082,69 @@ class EIR_TX_Power_Level(EIR_Element):
fields_desc = [SignedByteField("level", 0)]


class EIR_ClassOfDevice(EIR_Element):
name = 'Class of device'
fields_desc = [
FlagsField('major_service_classes', 0, 11, [
'limited_discoverable_mode',
'le_audio',
'reserved',
'positioning',
'networking',
'rendering',
'capturing',
'object_transfer',
'audio',
'telephony',
'information'
], tot_size=-3),
BitEnumField('major_device_class', 0, 5, {
0x00: 'miscellaneous',
0x01: 'computer',
0x02: 'phone',
0x03: 'lan',
0x04: 'audio_video',
0x05: 'peripheral',
0x06: 'imaging',
0x07: 'wearable',
0x08: 'toy',
0x09: 'health',
0x1f: 'uncategorized'
}),
BitField('minor_device_class', 0, 6),
BitField('fixed', 0, 2, end_tot_size=-3)
]


class EIR_SecureSimplePairingHashC192(EIR_Element):
name = 'Secure Simple Pairing Hash C-192'
fields_desc = [NBytesField('hash', 0, 16)]


class EIR_SecureSimplePairingRandomizerR192(EIR_Element):
name = 'Secure Simple Pairing Randomizer R-192'
fields_desc = [NBytesField('randomizer', 0, 16)]


class EIR_SecurityManagerOOBFlags(EIR_Element):
name = 'Security Manager Out of Band Flags'
fields_desc = [
BitField('oob_flags_field', 0, 1),
BitField('le_supported', 0, 1),
BitField('previously_used', 0, 1),
BitField('address_type', 0, 1),
BitField('reserved', 0, 4)
]


class EIR_PeripheralConnectionIntervalRange(EIR_Element):
name = 'Peripheral Connection Interval Range'
fields_desc = [
LEShortField('conn_interval_min', 0xFFFF),
LEShortField('conn_interval_max', 0xFFFF)
]


class EIR_Manufacturer_Specific_Data(EIR_Element):
name = "EIR Manufacturer Specific Data"
fields_desc = [
Expand Down Expand Up @@ -1154,6 +1232,30 @@ def extract_padding(self, s):
return s[:plen], s[plen:]


class EIR_ServiceData32BitUUID(EIR_Element):
name = 'EIR Service Data - 32-bit UUID'
fields_desc = [
XLEIntField('svc_uuid', 0),
]

def extract_padding(self, s):
# Needed to end each EIR_Element packet and make PacketListField work.
plen = EIR_Element.length_from(self) - 4
return s[:plen], s[plen:]


class EIR_ServiceData128BitUUID(EIR_Element):
name = 'EIR Service Data - 128-bit UUID'
fields_desc = [
UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)
]

def extract_padding(self, s):
# Needed to end each EIR_Element packet and make PacketListField work.
plen = EIR_Element.length_from(self) - 16
return s[:plen], s[plen:]


class HCI_Command_Hdr(Packet):
name = "HCI Command header"
fields_desc = [XBitField("ogf", 0, 6, tot_size=-2),
Expand Down Expand Up @@ -2231,13 +2333,22 @@ class HCI_LE_Meta_Long_Term_Key_Request(Packet):
bind_layers(EIR_Hdr, EIR_Flags, type=0x01)
bind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)
bind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)
bind_layers(EIR_Hdr, EIR_IncompleteList32BitServiceUUIDs, type=0x04)
bind_layers(EIR_Hdr, EIR_CompleteList32BitServiceUUIDs, type=0x05)
bind_layers(EIR_Hdr, EIR_IncompleteList128BitServiceUUIDs, type=0x06)
bind_layers(EIR_Hdr, EIR_CompleteList128BitServiceUUIDs, type=0x07)
bind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)
bind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)
bind_layers(EIR_Hdr, EIR_Device_ID, type=0x10)
bind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)
bind_layers(EIR_Hdr, EIR_ClassOfDevice, type=0x0d)
bind_layers(EIR_Hdr, EIR_SecureSimplePairingHashC192, type=0x0e)
bind_layers(EIR_Hdr, EIR_SecureSimplePairingRandomizerR192, type=0x0f)
bind_layers(EIR_Hdr, EIR_SecurityManagerOOBFlags, type=0x11)
bind_layers(EIR_Hdr, EIR_PeripheralConnectionIntervalRange, type=0x12)
bind_layers(EIR_Hdr, EIR_ServiceData16BitUUID, type=0x16)
bind_layers(EIR_Hdr, EIR_ServiceData32BitUUID, type=0x20)
bind_layers(EIR_Hdr, EIR_ServiceData128BitUUID, type=0x21)
bind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)
bind_layers(EIR_Hdr, EIR_Raw)

Expand Down
26 changes: 26 additions & 0 deletions test/scapy/layers/bluetooth.uts
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,32 @@ assert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].timeout == 60


+ Bluetooth LE Advertising / Scan Response Data Parsing
= Parse EIR_IncompleteList32BitServiceUUIDs

p = HCI_Hdr(hex_bytes('042fff019cc888f640c401000c025af32cb09904f6dc73222396f640c40c025a40dbca09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
assert EIR_IncompleteList32BitServiceUUIDs in p
assert len(p[EIR_IncompleteList32BitServiceUUIDs].svc_uuids) == 38

= Parse EIR_CompleteList32BitServiceUUIDs
antoniovazquezblanco marked this conversation as resolved.
Show resolved Hide resolved

p = HCI_Hdr(hex_bytes('042fff0106ec883aef1801003c04285758b30e0954562064656c2073616cc3b36e09030a110c110e1100120105810700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
assert EIR_CompleteList32BitServiceUUIDs in p
assert p[EIR_CompleteList32BitServiceUUIDs].svc_uuids == []

= Parse EIR_ClassOfDevice

p = HCI_Hdr(hex_bytes('043e2b020100000a1bb44ce0001f02010503ff000106084d4920524303021218040d040500020a0004fe06ec88a2'))
assert EIR_ClassOfDevice in p
assert p[EIR_ClassOfDevice].major_service_classes == 0
assert p[EIR_ClassOfDevice].major_device_class == 5
assert p[EIR_ClassOfDevice].minor_device_class == 1

= Parse EIR_ServiceData32BitUUID

p = HCI_Hdr(hex_bytes('042fff01c47c80894df801000c0128a269a30c4a125d13f30196894df80c012820f61a1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
assert EIR_ServiceData32BitUUID in p
assert p[EIR_ServiceData32BitUUID].svc_uuid == 0x001a1af6

= Parse EIR_Flags, EIR_CompleteList16BitServiceUUIDs, EIR_CompleteLocalName and EIR_TX_Power_Level

ad_report_raw_data = \
Expand Down
Loading