xref: /btstack/tool/sm_random_check.py (revision 6b7b368a289211554315a92f93a88e008a0f63b9)
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