mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-03 23:47:08 +00:00
137 lines
3.3 KiB
Python
Executable File
137 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# BlueKitchen GmbH (c) 2022
|
|
|
|
# parse PacketLogger and dump encryption keys
|
|
|
|
import sys
|
|
import datetime
|
|
import struct
|
|
|
|
|
|
def as_hex(data):
|
|
str_list = []
|
|
for byte in data:
|
|
str_list.append("{0:02x} ".format(byte))
|
|
return ''.join(str_list)
|
|
|
|
|
|
def as_key(data):
|
|
str_list = []
|
|
for byte in data:
|
|
str_list.append("{0:02x}".format(byte))
|
|
return ''.join(str_list)
|
|
|
|
|
|
def as_bd_addr(data):
|
|
str_list = []
|
|
for byte in data:
|
|
str_list.append("{0:02x}".format(byte))
|
|
return ':'.join(str_list)
|
|
|
|
|
|
def read_header(f):
|
|
bytes_read = f.read(13)
|
|
if bytes_read:
|
|
return struct.unpack(">IIIB", bytes_read)
|
|
else:
|
|
return (-1, 0, 0, 0)
|
|
|
|
|
|
def handle_at_offset(data, offset):
|
|
return struct.unpack_from("<H", data, offset)[0];
|
|
|
|
|
|
def bd_addr_at_offset(data, offset):
|
|
peer_addr = reversed(data[offset:offset + 6])
|
|
return as_bd_addr(peer_addr)
|
|
|
|
|
|
class hci_connection:
|
|
|
|
def __init__(self, bd_addr, con_handle):
|
|
self.bd_addr = bd_addr
|
|
self.con_handle = con_handle;
|
|
|
|
|
|
def connection_for_handle(con_handle):
|
|
if con_handle in connections:
|
|
return connections[con_handle]
|
|
else:
|
|
return None
|
|
|
|
|
|
def handle_cmd(packet):
|
|
opcode = struct.unpack_from("<H", packet, 0)[0];
|
|
if opcode == 0x201a:
|
|
# LE Long Term Key Request Reply
|
|
con_handle = handle_at_offset(packet, 3)
|
|
conn = connection_for_handle(con_handle)
|
|
print("LE LTK for %s - %s" % (conn.bd_addr, as_key(reversed(packet[5:5+16]))))
|
|
elif opcode == 0x2019:
|
|
# LE Enable Encryption command
|
|
con_handle = handle_at_offset(packet, 3)
|
|
conn = connection_for_handle(con_handle)
|
|
print("LE LTK for %s - %s" % (conn.bd_addr, as_key(reversed(packet[15:15+16]))))
|
|
elif opcode == 0x040b:
|
|
# Link Key Request Reply
|
|
bd_addr = bd_addr_at_offset(packet, 3)
|
|
print("Link Key for %s - %s" % (bd_addr, as_key(reversed(packet[9:9+16]))))
|
|
|
|
def handle_evt(event):
|
|
if event[0] == 0x05:
|
|
# Disconnection Complete
|
|
con_handle = handle_at_offset(event, 3)
|
|
print("Disconnection Complete: handle 0x%04x" % con_handle)
|
|
connections.pop(con_handle, None)
|
|
elif event[0] == 0x18:
|
|
# Link Key Notification
|
|
bd_addr = bd_addr_at_offset(packet, 2)
|
|
print("Link Key for %s - %s" % (bd_addr, as_key(reversed(packet[8:8+16]))))
|
|
elif event[0] == 0x3e:
|
|
if event[2] == 0x01:
|
|
# LE Connection Complete
|
|
con_handle = handle_at_offset(event, 4);
|
|
peer_addr = bd_addr_at_offset(event, 8)
|
|
connection = hci_connection(peer_addr, con_handle)
|
|
connections[con_handle] = connection
|
|
print("LE Connection Complete: %s handle 0x%04x" % (peer_addr, con_handle))
|
|
|
|
|
|
# globals
|
|
connections = {}
|
|
|
|
if len(sys.argv) == 1:
|
|
print ('Dump encryptiong keys from PacketLogger trace file')
|
|
print ('Copyright 2023, BlueKitchen GmbH')
|
|
print ('')
|
|
print ('Usage: ', sys.argv[0], 'hci_dump.pklg')
|
|
exit(0)
|
|
|
|
infile = sys.argv[1]
|
|
|
|
with open (infile, 'rb') as fin:
|
|
pos = 0
|
|
try:
|
|
while True:
|
|
(entry_len, ts_sec, ts_usec, type) = read_header(fin)
|
|
if entry_len < 0:
|
|
break
|
|
packet_len = entry_len - 9
|
|
if packet_len > 66000:
|
|
print ("Error parsing pklg at offset %u (%x)." % (pos, pos))
|
|
break
|
|
packet = fin.read(packet_len)
|
|
pos = pos + 4 + entry_len
|
|
if type == 0x00:
|
|
handle_cmd(packet)
|
|
elif type == 0x01:
|
|
handle_evt(packet)
|
|
elif type == 0x02:
|
|
pass
|
|
elif type == 0x03:
|
|
pass
|
|
|
|
except TypeError as e:
|
|
print(e)
|
|
print ("Error parsing pklg at offset %u (%x)." % (pos, pos))
|