1*6b7b368aSMatthias Ringwald#!/usr/bin/env python 2*6b7b368aSMatthias Ringwald# BlueKitchen GmbH (c) 2014 3*6b7b368aSMatthias Ringwald 4*6b7b368aSMatthias Ringwald# Report SM Pairing Random packets with value zero 5*6b7b368aSMatthias Ringwald 6*6b7b368aSMatthias Ringwald 7*6b7b368aSMatthias Ringwaldimport re 8*6b7b368aSMatthias Ringwaldimport sys 9*6b7b368aSMatthias Ringwaldimport time 10*6b7b368aSMatthias Ringwaldimport datetime 11*6b7b368aSMatthias Ringwald 12*6b7b368aSMatthias Ringwaldpacket_types = [ "CMD =>", "EVT <=", "ACL =>", "ACL <="] 13*6b7b368aSMatthias Ringwald 14*6b7b368aSMatthias Ringwalddef read_net_32(f): 15*6b7b368aSMatthias Ringwald a = f.read(1) 16*6b7b368aSMatthias Ringwald if a == '': 17*6b7b368aSMatthias Ringwald return -1 18*6b7b368aSMatthias Ringwald b = f.read(1) 19*6b7b368aSMatthias Ringwald if b == '': 20*6b7b368aSMatthias Ringwald return -1 21*6b7b368aSMatthias Ringwald c = f.read(1) 22*6b7b368aSMatthias Ringwald if c == '': 23*6b7b368aSMatthias Ringwald return -1 24*6b7b368aSMatthias Ringwald d = f.read(1) 25*6b7b368aSMatthias Ringwald if d == '': 26*6b7b368aSMatthias Ringwald return -1 27*6b7b368aSMatthias Ringwald return ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d) 28*6b7b368aSMatthias Ringwald 29*6b7b368aSMatthias Ringwalddef as_hex(data): 30*6b7b368aSMatthias Ringwald str_list = [] 31*6b7b368aSMatthias Ringwald for byte in data: 32*6b7b368aSMatthias Ringwald str_list.append("{0:02x} ".format(ord(byte))) 33*6b7b368aSMatthias Ringwald return ''.join(str_list) 34*6b7b368aSMatthias Ringwald 35*6b7b368aSMatthias Ringwalddef check_file(infile): 36*6b7b368aSMatthias Ringwald with open (infile, 'rb') as fin: 37*6b7b368aSMatthias Ringwald pos = 0 38*6b7b368aSMatthias Ringwald warning = True 39*6b7b368aSMatthias Ringwald try: 40*6b7b368aSMatthias Ringwald while True: 41*6b7b368aSMatthias Ringwald len = read_net_32(fin) 42*6b7b368aSMatthias Ringwald if len < 0: 43*6b7b368aSMatthias Ringwald break 44*6b7b368aSMatthias Ringwald ts_sec = read_net_32(fin) 45*6b7b368aSMatthias Ringwald ts_usec = read_net_32(fin) 46*6b7b368aSMatthias Ringwald type = ord(fin.read(1)) 47*6b7b368aSMatthias Ringwald packet_len = len - 9; 48*6b7b368aSMatthias Ringwald if (packet_len > 66000): 49*6b7b368aSMatthias Ringwald print ("Error parsing pklg at offset %u (%x)." % (pos, pos)) 50*6b7b368aSMatthias Ringwald break 51*6b7b368aSMatthias Ringwald packet = fin.read(packet_len) 52*6b7b368aSMatthias Ringwald pos = pos + 4 + len 53*6b7b368aSMatthias Ringwald time = "[%s.%03u]" % (datetime.datetime.fromtimestamp(ts_sec).strftime("%Y-%m-%d %H:%M:%S"), ts_usec / 1000) 54*6b7b368aSMatthias Ringwald if type not in [0x02, 0x03]: 55*6b7b368aSMatthias Ringwald continue 56*6b7b368aSMatthias Ringwald packet_boundary_flags = (ord(packet[1]) >> 4) & 3 57*6b7b368aSMatthias Ringwald if packet_boundary_flags not in [0x00, 0x02]: 58*6b7b368aSMatthias Ringwald continue 59*6b7b368aSMatthias Ringwald channel = ord(packet[6]) | (ord(packet[7]) << 8) 60*6b7b368aSMatthias Ringwald if channel != 0x06: 61*6b7b368aSMatthias Ringwald continue 62*6b7b368aSMatthias Ringwald smp_command = ord(packet[8]) 63*6b7b368aSMatthias Ringwald if smp_command != 4: 64*6b7b368aSMatthias Ringwald continue 65*6b7b368aSMatthias Ringwald random = [ ord(i) for i in packet[9:25] ] 66*6b7b368aSMatthias Ringwald num_zeros = random.count(0) 67*6b7b368aSMatthias Ringwald if num_zeros != 16: 68*6b7b368aSMatthias Ringwald continue 69*6b7b368aSMatthias Ringwald if warning: 70*6b7b368aSMatthias Ringwald print("%s contains SM Pairing Random command with Zeroes:" % infile) 71*6b7b368aSMatthias Ringwald warning = False 72*6b7b368aSMatthias Ringwald print time, packet_types[type], as_hex(packet) 73*6b7b368aSMatthias Ringwald 74*6b7b368aSMatthias Ringwald if not warning: 75*6b7b368aSMatthias Ringwald print("") 76*6b7b368aSMatthias Ringwald 77*6b7b368aSMatthias Ringwald except TypeError: 78*6b7b368aSMatthias Ringwald print ("Error parsing pklg at offset %u (%x)." % (pos, pos)) 79*6b7b368aSMatthias Ringwald 80*6b7b368aSMatthias Ringwaldif len(sys.argv) == 1: 81*6b7b368aSMatthias Ringwald print 'Usage: ', sys.argv[0], 'hci_dump.pklg' 82*6b7b368aSMatthias Ringwald exit(0) 83*6b7b368aSMatthias Ringwald 84*6b7b368aSMatthias Ringwaldfor infile in sys.argv[2:]: 85*6b7b368aSMatthias Ringwald check_file(infile) 86*6b7b368aSMatthias Ringwald 87*6b7b368aSMatthias Ringwaldinfile = sys.argv[1] 88*6b7b368aSMatthias Ringwald 89