1
0
mirror of https://github.com/bluekitchen/btstack.git synced 2025-03-25 16:43:28 +00:00

pts/sm_test: simulate OOB data exchange, trigger pairing manually as well

This commit is contained in:
Matthias Ringwald 2018-04-03 15:43:51 +02:00
parent b0ecbe6b0a
commit f4487237df
2 changed files with 121 additions and 36 deletions

@ -80,14 +80,24 @@ static uint8_t 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, };
// legacy pairing oob
static uint8_t sm_oob_tk_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
// sc pairing oob
static uint8_t sm_oob_local_random[16];
static uint8_t sm_oob_peer_random[16];
static uint8_t sm_oob_peer_confirm[16];
static int we_are_central = 0;
static bd_addr_t peer_address;
static int ui_passkey = 0;
static int ui_digits_for_passkey = 0;
static int ui_oob_confirm;
static int ui_oob_random;
static int ui_oob_pos;
static int ui_oob_nibble;
static btstack_timer_source_t heartbeat;
static uint8_t counter = 0;
@ -123,6 +133,34 @@ static void heartbeat_handler(struct btstack_timer_source *ts){
counter++;
}
static int get_oob_data_callback(uint8_t address_type, bd_addr_t addr, uint8_t * oob_data){
UNUSED(address_type);
(void)addr;
log_info("get_oob_data_callback for %s", bd_addr_to_str(addr));
if(!sm_have_oob_data) return 0;
memcpy(oob_data, sm_oob_tk_data, 16);
return 1;
}
static int get_sc_oob_data_callback(uint8_t address_type, bd_addr_t addr, uint8_t * oob_sc_peer_confirm, uint8_t * oob_sc_peer_random){
UNUSED(address_type);
(void)addr;
log_info("get_sc_oob_data_callback for %s", bd_addr_to_str(addr));
if(!sm_have_oob_data) return 0;
memcpy(oob_sc_peer_confirm, sm_oob_peer_confirm, 16);
memcpy(oob_sc_peer_random, sm_oob_peer_random, 16);
return 1;
}
static void sc_local_oob_generated_callback(const uint8_t * confirm_value, const uint8_t * random_value){
printf("LOCAL_OOB_CONFIRM: ");
printf_hexdump(confirm_value, 16);
printf("LOCAL_OOB_RANDOM: ");
printf_hexdump(random_value, 16);
fflush(stdout);
memcpy(sm_oob_local_random, random_value, 16);
}
// ATT Client Read Callback for Dynamic Data
// - if buffer == NULL, don't copy data, just return size of value
// - if buffer != NULL, copy data and return number bytes copied
@ -234,14 +272,6 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
fflush(stdout);
}
static void sc_oob_callback(const uint8_t * confirm_value, const uint8_t * random_value){
printf("OOB_CONFIRM: ");
printf_hexdump(confirm_value, 16);
printf("OOB_RANDOM: ");
printf_hexdump(random_value, 16);
fflush(stdout);
}
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
@ -255,7 +285,7 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
gap_local_bd_addr(local_addr);
printf("BD_ADDR: %s\n", bd_addr_to_str(local_addr));
// generate OOB data
sm_generate_sc_oob_data(sc_oob_callback);
sm_generate_sc_oob_data(sc_local_oob_generated_callback);
}
break;
case HCI_EVENT_LE_META:
@ -263,10 +293,6 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
connection_handle = little_endian_read_16(packet, 4);
printf("CONNECTED: Connection handle 0x%04x\n", connection_handle);
if (we_are_central){
printf("REQUEST_PAIRING\n");
sm_request_pairing(connection_handle);
}
break;
default:
break;
@ -333,6 +359,41 @@ static void stdin_process(char c){
return;
}
if (ui_oob_confirm){
if (c == ' ') return;
ui_oob_nibble = (ui_oob_nibble << 4) | nibble_for_char(c);
if ((ui_oob_pos & 1) == 1){
sm_oob_peer_confirm[ui_oob_pos >> 1] = ui_oob_nibble;
ui_oob_nibble = 0;
}
ui_oob_pos++;
if (ui_oob_pos == 32){
ui_oob_confirm = 0;
printf("PEER_OOB_CONFIRM: ");
printf_hexdump(sm_oob_peer_confirm, 16);
fflush(stdout);
}
return;
}
if (ui_oob_random){
if (c == ' ') return;
ui_oob_nibble = (ui_oob_nibble << 4) | nibble_for_char(c);
if ((ui_oob_pos & 1) == 1){
sm_oob_peer_random[ui_oob_pos >> 1] = ui_oob_nibble;
ui_oob_nibble = 0;
}
ui_oob_pos++;
if (ui_oob_pos == 32){
ui_oob_random = 0;
printf("PEER_OOB_RANDOM: ");
printf_hexdump(sm_oob_peer_random, 16);
fflush(stdout);
}
return;
}
switch (c){
case 'a': // accept just works
printf("accepting just works\n");
@ -346,9 +407,19 @@ static void stdin_process(char c){
printf("decline bonding\n");
sm_bonding_decline(connection_handle);
break;
case 'g':
printf("generate oob data\n");
sm_generate_sc_oob_data(sc_oob_callback);
case 'o':
printf("receive oob confirm value\n");
ui_oob_confirm = 1;
ui_oob_pos = 0;
break;
case 'r':
printf("receive oob random value\n");
ui_oob_random = 1;
ui_oob_pos = 0;
break;
case 'p':
printf("REQUEST_PAIRING\n");
sm_request_pairing(connection_handle);
break;
case 'x':
printf("Exit\n");
@ -361,15 +432,6 @@ static void stdin_process(char c){
return;
}
static int get_oob_data_callback(uint8_t address_type, bd_addr_t addr, uint8_t * oob_data){
UNUSED(address_type);
log_info("get_oob_data_callback for %s", bd_addr_to_str(addr));
(void)addr;
if(!sm_have_oob_data) return 0;
memcpy(oob_data, sm_oob_data, 16);
return 1;
}
int btstack_main(int argc, const char * argv[]);
int btstack_main(int argc, const char * argv[]){
@ -440,6 +502,7 @@ int btstack_main(int argc, const char * argv[]){
sm_set_io_capabilities(sm_io_capabilities);
sm_set_authentication_requirements(sm_auth_req);
sm_register_oob_data_callback(get_oob_data_callback);
sm_register_sc_oob_data_callback(get_sc_oob_data_callback);
if (sm_failure < SM_REASON_NUMERIC_COMPARISON_FAILED && sm_failure != SM_REASON_PASSKEY_ENTRY_FAILED){
sm_test_set_pairing_failure(sm_failure);

@ -48,8 +48,8 @@ failures = [
# tester config
debug = False
regenerate = False
usb_paths = ['4', '6']
# usb_paths = ['3', '5']
# usb_paths = ['4', '6']
usb_paths = ['3', '5']
class Node:
@ -137,9 +137,7 @@ class Node:
self.peer_addr = addr
def write(self, string):
for c in string:
self.stdin.write(string)
time.sleep (0.1);
self.stdin.write(string)
def terminate(self):
self.write('x')
@ -184,18 +182,39 @@ def run(test_descriptor, nodes):
master.set_failure(test_descriptor['tester_failure'])
master.start_process()
nodes.append(master)
if state == 'W4_MASTER_BD_ADDR':
#
if node.get_name() == 'iut':
iut_node = node
tester_node = master
else:
iut_node = master
tester_node = node
elif state == 'W4_MASTER_BD_ADDR':
# central started, start connecting
node.write('c')
elif line.startswith('OOB_CONFIRM:'):
print('start to connect')
state = 'W4_CONNECTED'
elif line.startswith('LOCAL_OOB_CONFIRM:'):
confirm = line.split('OOB_CONFIRM: ')[1]
test_descriptor[node.get_name()+'_oob_confirm'] = confirm
elif line.startswith('OOB_RANDOM:'):
elif line.startswith('LOCAL_OOB_RANDOM:'):
random = line.split('OOB_RANDOM: ')[1]
test_descriptor[node.get_name()+'_oob_random'] = random
elif line.startswith('CONNECTED:'):
print('%s connected' % node.get_name())
if state == 'W4_CONNECTED':
if state == 'W4_CONNECTED' and node == nodes[1]:
# simulate OOK exchange if requested
if test_descriptor['tester_oob_data'] == '1':
print('Simulate IUT -> Tester OOB')
tester_node.write('o' + test_descriptor['iut_oob_confirm'])
tester_node.write('r' + test_descriptor['iut_oob_random'])
test_descriptor['method'] = 'OOB'
if test_descriptor['iut_oob_data'] == '1':
print('Simulate Tester -> IUT OOB')
iut_node.write('o' + test_descriptor['tester_oob_confirm'])
iut_node.write('r' + test_descriptor['tester_oob_random'])
test_descriptor['method'] = 'OOB'
node.write('p')
state = 'W4_PAIRING'
elif line.startswith('JUST_WORKS_REQUEST'):
print('%s just works requested' % node.get_name())
@ -411,6 +430,7 @@ def run_test(test_descriptor):
except KeyboardInterrupt:
print('Interrupted')
test_descriptor['interrupted'] = 'EXIT'
# shutdown
for node in nodes:
@ -444,3 +464,5 @@ with open('sm_test.csv') as csvfile:
print(test_descriptor)
run_test(test_descriptor)
if 'interrupted' in test_descriptor:
break