pts/sm_test: allow simulation of pairing failures

This commit is contained in:
Matthias Ringwald 2018-03-27 14:36:28 +02:00
parent 94145cfe40
commit ad912a6c9e
5 changed files with 143 additions and 15 deletions

1
test/pts/.gitignore vendored
View File

@ -23,3 +23,4 @@ sco_loopback
sco_loopbackiopt
sm_test.h
sm_test
SM_*

View File

@ -91,6 +91,7 @@ CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wunused-va
CFLAGS += -D ENABLE_LE_DATA_CHANNELS
CFLAGS += -D ENABLE_LE_SECURE_CONNECTIONS
CFLAGS += -D ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
CFLAGS += -D ENABLE_TESTING_SUPPORT
CFLAGS += -I..
CFLAGS += -I${BTSTACK_ROOT}/src
CFLAGS += -I${BTSTACK_ROOT}/src/classic

View File

@ -79,7 +79,7 @@ const uint8_t adv_data_len = sizeof(adv_data);
static int sm_have_oob_data = 0;
static uint8_t sm_io_capabilities = 0;
static uint8_t sm_auth_req = 0;
static uint8_t sm_failure = 0;
// static uint8_t * sm_oob_data = (uint8_t *) "0123456789012345"; // = { 0x30...0x39, 0x30..0x35}
static uint8_t sm_oob_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
@ -294,6 +294,7 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
case SM_EVENT_PAIRING_COMPLETE:
if (!wait_for_pairing_complete) break;
printf("PAIRING_COMPLETE: %u,%u\n", sm_event_pairing_complete_get_status(packet), sm_event_pairing_complete_get_reason(packet));
if (sm_event_pairing_complete_get_status(packet)) break;
if (we_are_central){
printf("Search for LE Counter service.\n");
state = TC_W4_SERVICE_RESULT;
@ -333,6 +334,10 @@ static void stdin_process(char c){
printf("accepting just works\n");
sm_just_works_confirm(connection_handle);
break;
case 'd':
printf("decline bonding\n");
sm_bonding_decline(connection_handle);
break;
case 'x':
printf("Exit\n");
exit(0);
@ -371,6 +376,10 @@ int btstack_main(int argc, const char * argv[]){
arg++;
sm_auth_req = atoi(argv[arg++]);
}
if(!strcmp(argv[arg], "-f") || !strcmp(argv[arg], "--failure")){
arg++;
sm_failure = atoi(argv[arg++]);
}
}
// parse command line flags
@ -378,6 +387,7 @@ int btstack_main(int argc, const char * argv[]){
printf("Security Managet Tester starting up...\n");
log_info("IO_CAPABILITIES: %u", sm_io_capabilities);
log_info("AUTH_REQ: %u", sm_auth_req);
log_info("FAILURE: %u", sm_failure);
if (we_are_central){
log_info("ROLE: CENTRAL");
} else {
@ -413,6 +423,10 @@ int btstack_main(int argc, const char * argv[]){
sm_set_authentication_requirements(sm_auth_req);
sm_register_oob_data_callback(get_oob_data_callback);
if (sm_failure < SM_REASON_NUMERIC_COMPARISON_FAILED){
sm_test_set_pairing_failure(sm_failure);
}
sm_event_callback_registration.callback = &app_packet_handler;
sm_add_event_handler(&sm_event_callback_registration);

View File

@ -1,2 +1,64 @@
name,iut_io_capabilities,tester_io_capabilities,iut_auth_req,tester_auth_req,iut_oob_data,tester_oob_data,
SM/MAS/SCJW/BV-01-C,0,0,8,8,0,0
name,iut_io_capabilities,tester_io_capabilities,iut_auth_req,tester_auth_req,iut_oob_data,tester_oob_data,tester_failure
# -- Just Works (SCJW) --
SM/MAS/SCJW/BV-01-C/01,0,0,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/02,1,0,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/03,3,0,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/04,0,1,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/05,1,1,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/06,3,1,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/07,4,1,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/08,3,2,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/09,0,3,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/10,1,3,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/11,2,3,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/12,3,3,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/13,4,3,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/14,1,4,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/15,3,4,8,8,0,0,0
SM/MAS/SCJW/BV-01-C/16,4,4,8,8,0,0,0
# same as SM/MAS/SCJW/BV-01, just with IUT in Responder role
SM/SLA/SCJW/BV-02-C/01,0,0,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/02,1,0,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/03,3,0,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/04,0,1,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/05,1,1,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/06,3,1,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/07,4,1,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/08,3,2,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/09,0,3,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/10,1,3,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/11,2,3,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/12,3,3,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/13,4,3,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/14,1,4,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/15,3,4,8,8,0,0,0
SM/SLA/SCJW/BV-02-C/16,4,4,8,8,0,0,0
# additional bits set in authreq
SM/SLA/SCJW/BV-03-C/01,3,3,8,72,0,0,0
SM/SLA/SCJW/BV-03-C/02,3,3,8,136,0,0,0
SM/SLA/SCJW/BV-03-C/03,3,3,8,200,0,0,0
# same as SM/SLA/SCJW/BV-03-C, just with IUT in Initiator role
SM/MAS/SCJW/BV-04-C/01,3,3,8,72,0,0,0
SM/MAS/SCJW/BV-04-C/02,3,3,8,136,0,0,0
SM/MAS/SCJW/BV-04-C/03,3,3,8,200,0,0,0
# tester responds with pairing failure in responder role
SM/MAS/SCJW/BI-01-C/01,0,0,8,8,0,0,3
SM/MAS/SCJW/BI-01-C/02,0,0,8,8,0,0,8
SM/MAS/SCJW/BI-01-C/03,0,0,8,8,0,0,5
SM/MAS/SCJW/BI-01-C/04,0,0,8,8,0,0,9
# tester responds with pairing failure during phase 2
SM/MAS/SCJW/BI-01-C/05,0,0,8,8,0,0,12
# tester responds with pairing failure during phase 2
SM/SLA/SCJW/BI-02-C,0,3,8,8,0,0,4

1 name,iut_io_capabilities,tester_io_capabilities,iut_auth_req,tester_auth_req,iut_oob_data,tester_oob_data, name,iut_io_capabilities,tester_io_capabilities,iut_auth_req,tester_auth_req,iut_oob_data,tester_oob_data,tester_failure
2 SM/MAS/SCJW/BV-01-C,0,0,8,8,0,0 # -- Just Works (SCJW) --
3 SM/MAS/SCJW/BV-01-C/01,0,0,8,8,0,0,0
4 SM/MAS/SCJW/BV-01-C/02,1,0,8,8,0,0,0
5 SM/MAS/SCJW/BV-01-C/03,3,0,8,8,0,0,0
6 SM/MAS/SCJW/BV-01-C/04,0,1,8,8,0,0,0
7 SM/MAS/SCJW/BV-01-C/05,1,1,8,8,0,0,0
8 SM/MAS/SCJW/BV-01-C/06,3,1,8,8,0,0,0
9 SM/MAS/SCJW/BV-01-C/07,4,1,8,8,0,0,0
10 SM/MAS/SCJW/BV-01-C/08,3,2,8,8,0,0,0
11 SM/MAS/SCJW/BV-01-C/09,0,3,8,8,0,0,0
12 SM/MAS/SCJW/BV-01-C/10,1,3,8,8,0,0,0
13 SM/MAS/SCJW/BV-01-C/11,2,3,8,8,0,0,0
14 SM/MAS/SCJW/BV-01-C/12,3,3,8,8,0,0,0
15 SM/MAS/SCJW/BV-01-C/13,4,3,8,8,0,0,0
16 SM/MAS/SCJW/BV-01-C/14,1,4,8,8,0,0,0
17 SM/MAS/SCJW/BV-01-C/15,3,4,8,8,0,0,0
18 SM/MAS/SCJW/BV-01-C/16,4,4,8,8,0,0,0
19 # same as SM/MAS/SCJW/BV-01, just with IUT in Responder role
20 SM/SLA/SCJW/BV-02-C/01,0,0,8,8,0,0,0
21 SM/SLA/SCJW/BV-02-C/02,1,0,8,8,0,0,0
22 SM/SLA/SCJW/BV-02-C/03,3,0,8,8,0,0,0
23 SM/SLA/SCJW/BV-02-C/04,0,1,8,8,0,0,0
24 SM/SLA/SCJW/BV-02-C/05,1,1,8,8,0,0,0
25 SM/SLA/SCJW/BV-02-C/06,3,1,8,8,0,0,0
26 SM/SLA/SCJW/BV-02-C/07,4,1,8,8,0,0,0
27 SM/SLA/SCJW/BV-02-C/08,3,2,8,8,0,0,0
28 SM/SLA/SCJW/BV-02-C/09,0,3,8,8,0,0,0
29 SM/SLA/SCJW/BV-02-C/10,1,3,8,8,0,0,0
30 SM/SLA/SCJW/BV-02-C/11,2,3,8,8,0,0,0
31 SM/SLA/SCJW/BV-02-C/12,3,3,8,8,0,0,0
32 SM/SLA/SCJW/BV-02-C/13,4,3,8,8,0,0,0
33 SM/SLA/SCJW/BV-02-C/14,1,4,8,8,0,0,0
34 SM/SLA/SCJW/BV-02-C/15,3,4,8,8,0,0,0
35 SM/SLA/SCJW/BV-02-C/16,4,4,8,8,0,0,0
36 # additional bits set in authreq
37 SM/SLA/SCJW/BV-03-C/01,3,3,8,72,0,0,0
38 SM/SLA/SCJW/BV-03-C/02,3,3,8,136,0,0,0
39 SM/SLA/SCJW/BV-03-C/03,3,3,8,200,0,0,0
40 # same as SM/SLA/SCJW/BV-03-C, just with IUT in Initiator role
41 SM/MAS/SCJW/BV-04-C/01,3,3,8,72,0,0,0
42 SM/MAS/SCJW/BV-04-C/02,3,3,8,136,0,0,0
43 SM/MAS/SCJW/BV-04-C/03,3,3,8,200,0,0,0
44 # tester responds with pairing failure in responder role
45 SM/MAS/SCJW/BI-01-C/01,0,0,8,8,0,0,3
46 SM/MAS/SCJW/BI-01-C/02,0,0,8,8,0,0,8
47 SM/MAS/SCJW/BI-01-C/03,0,0,8,8,0,0,5
48 SM/MAS/SCJW/BI-01-C/04,0,0,8,8,0,0,9
49 # tester responds with pairing failure during phase 2
50 SM/MAS/SCJW/BI-01-C/05,0,0,8,8,0,0,12
51 # tester responds with pairing failure during phase 2
52 SM/SLA/SCJW/BI-02-C,0,3,8,8,0,0,4
53
54
55
56
57
58
59
60
61
62
63
64

View File

@ -29,8 +29,25 @@ SM_AUTHREQ_MITM_PROTECTION = 0x04
SM_AUTHREQ_SECURE_CONNECTION = 0x08
SM_AUTHREQ_KEYPRESS = 0x10
failures = [
'RESERVED',
'PASSKEY_ENTRY_FAILED',
'OOB_NOT_AVAILABLE',
'AUTHENTHICATION_REQUIREMENTS',
'CONFIRM_VALUE_FAILED',
'PAIRING_NOT_SUPPORTED',
'ENCRYPTION_KEY_SIZE',
'COMMAND_NOT_SUPPORTED',
'UNSPECIFIED_REASON',
'REPEATED_ATTEMPTS',
'INVALID_PARAMETERS',
'DHKEY_CHECK_FAILED',
'NUMERIC_COMPARISON_FAILED',
]
# tester config
regenerate = True
debug = True
regenerate = False
# usb_paths = ['4', '6']
usb_paths = ['3', '5']
@ -40,6 +57,7 @@ class Node:
self.name = 'node'
self._got_line = False
self.peer_addr = None
self.failure = None
def get_name(self):
return self.name
@ -56,6 +74,9 @@ class Node:
def set_oob_data(self, oob_data):
self.oob_data = oob_data
def set_failure(self, failure):
self.failure = failure
def set_usb_path(self, path):
self.usb_path = path
@ -86,6 +107,9 @@ class Node:
if self.peer_addr != None:
args.append('-a')
args.append(self.peer_addr)
if self.failure != None:
args.append('-f')
args.append(self.failure)
args.append('-r')
args.append(self.auth_req)
print('%s - "%s"' % (self.name, ' '.join(args)))
@ -128,7 +152,8 @@ def run(test_descriptor, nodes):
node.read_stdout()
if node.got_line():
line = node.fetch_line()
# print('%s: %s' % (node.get_name(), line))
if debug:
print('%s: %s' % (node.get_name(), line))
if line.startswith('Packet Log: '):
path = line.split(': ')[1]
node.set_packet_log(path)
@ -148,6 +173,8 @@ def run(test_descriptor, nodes):
master.set_peer_addr(addr)
master.set_auth_req(test_descriptor[master_role + '_auth_req'])
master.set_io_capabilities(test_descriptor[master_role + '_io_capabilities'])
if master_role == 'tester':
master.set_failure(test_descriptor['tester_failure'])
master.start_process()
nodes.append(master)
if line.startswith('CONNECTED:'):
@ -156,7 +183,12 @@ def run(test_descriptor, nodes):
state = 'W4_PAIRING'
if line.startswith('JUST_WORKS_REQUEST'):
print('%s just works requested' % node.get_name())
node.write('a')
if node.get_name() == 'tester' and test_descriptor['tester_failure'] == '12':
print('Decline bonding')
node.write('d')
else:
print('Accept bonding')
node.write('a')
if line.startswith('PAIRING_COMPLETE'):
result = line.split(': ')[1]
(status,reason) = result.split(',')
@ -179,9 +211,11 @@ def write_config(fout, test_descriptor):
'---',
'bd_addr',
'role',
'failure',
'io_capabilities',
'mitm',
'secure_connection',
'rfu',
'oob_data',
'pairing_complete_status',
'pairing_complete_reason']
@ -190,8 +224,8 @@ def write_config(fout, test_descriptor):
fout.write('Test: %s\n' % test_descriptor['name'])
fout.write('Date: %s\n' % str(datetime.datetime.now()))
fout.write('\n')
attribute_len = 25
value_len = 30
attribute_len = 28
value_len = 35
format_string = '%%-%us|%%-%us|%%-%us\n' % (attribute_len, value_len, value_len)
for attribute in attributes:
name = attribute
@ -212,6 +246,12 @@ def write_config(fout, test_descriptor):
elif attribute == 'secure_connection':
iut = (int(test_descriptor['iut_auth_req' ]) & SM_AUTHREQ_SECURE_CONNECTION) >> 3
tester = (int(test_descriptor['tester_auth_req']) & SM_AUTHREQ_SECURE_CONNECTION) >> 3
elif attribute == 'rfu':
iut = (int(test_descriptor['iut_auth_req' ]) & 192) >> 6
tester = (int(test_descriptor['tester_auth_req']) & 192) >> 6
elif attribute == 'failure':
iut = ''
tester = failures[int(test_descriptor['tester_failure'])]
else:
iut = test_descriptor['iut_' + attribute]
tester = test_descriptor['tester_' + attribute]
@ -235,16 +275,18 @@ def run_test(test_descriptor):
if '/SLA/' in test_descriptor['name']:
iut_role = 'responder'
tester_role = 'master'
tester_role = 'initiator'
slave_role = 'iut'
test_descriptor['master_role'] = 'tester'
master_role = 'tester'
else:
iut_role = 'initiator'
tester_role = "slave"
tester_role = 'responder'
slave_role = 'tester'
test_descriptor['master_role'] = 'iut'
master_role = 'iut'
test_descriptor['iut_role' ] = iut_role
test_descriptor['tester_role'] = tester_role
test_descriptor['master_role'] = master_role
test_descriptor['slave_role'] = slave_role
slave = Node()
@ -253,6 +295,8 @@ def run_test(test_descriptor):
slave.usb_path = usb_paths[0]
slave.set_auth_req(test_descriptor[slave_role + '_auth_req'])
slave.set_io_capabilities(test_descriptor[slave_role + '_io_capabilities'])
if slave_role == 'tester':
slave.set_failure(test_descriptor['tester_failure'])
# start up slave
slave.start_process()
@ -264,7 +308,7 @@ def run_test(test_descriptor):
run(test_descriptor, nodes)
# identify iut and tester
if iut_role == 'slave':
if iut_role == 'responder':
iut = nodes[0]
tester = nodes[1]
else:
@ -274,12 +318,12 @@ def run_test(test_descriptor):
# move hci logs into result folder
test_folder = test_descriptor['test_folder']
os.makedirs(test_folder)
shutil.move(iut.get_packet_log(), test_folder + '/iut.pklg')
shutil.move(iut.get_packet_log(), test_folder + '/iut.pklg')
shutil.move(tester.get_packet_log(), test_folder + '/tester.pklg')
# write config
with open (test_folder + '/config.txt', "wt") as fout:
test_descriptor['iut_bd_addr'] = iut.get_bd_addr()
test_descriptor['iut_bd_addr'] = iut.get_bd_addr()
test_descriptor['tester_bd_addr'] = tester.get_bd_addr()
write_config(fout, test_descriptor)
@ -297,6 +341,12 @@ with open('sm_test.csv') as csvfile:
reader = csv.DictReader(csvfile)
for test_descriptor in reader:
test_name = test_descriptor['name']
if test_name.startswith('#'):
continue
if len(test_name) == 0:
continue
test_folder = test_name.replace('/', '_')
test_descriptor['test_folder'] = test_folder