mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-04 06:39:53 +00:00
Merge branch 'master' of https://github.com/bluekitchen/btstack
This commit is contained in:
commit
08d5b4cc31
@ -292,7 +292,7 @@ static void att_run(void){
|
||||
switch (sm_authorization_state(att_client_addr_type, att_client_address)){
|
||||
case AUTHORIZATION_UNKNOWN:
|
||||
l2cap_release_packet_buffer();
|
||||
sm_request_authorization(att_client_addr_type, att_client_address);
|
||||
sm_request_pairing(att_client_addr_type, att_client_address);
|
||||
return;
|
||||
case AUTHORIZATION_PENDING:
|
||||
l2cap_release_packet_buffer();
|
||||
|
@ -735,9 +735,8 @@ static void gatt_client_run(void){
|
||||
switch (peripheral->gatt_client_state){
|
||||
case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
|
||||
case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
|
||||
|
||||
if (peripheral->attribute_length < peripheral_mtu(peripheral) - 3) break;
|
||||
printf(".. ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH %u > %u\n", peripheral->attribute_length, peripheral_mtu(peripheral));
|
||||
if (peripheral->attribute_length <= peripheral_mtu(peripheral) - 3) break;
|
||||
log_error("gatt_client_run: value len %u > MTU %u - 3\n", peripheral->attribute_length, peripheral_mtu(peripheral));
|
||||
gatt_client_handle_transaction_complete(peripheral);
|
||||
emit_gatt_complete_event(peripheral, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
|
||||
return;
|
||||
@ -1418,7 +1417,7 @@ le_command_status_t gatt_client_write_value_of_characteristic_without_response(u
|
||||
if (!peripheral) return (le_command_status_t) BTSTACK_MEMORY_ALLOC_FAILED;
|
||||
if (!is_ready(peripheral)) return BLE_PERIPHERAL_IN_WRONG_STATE;
|
||||
|
||||
if (value_length >= peripheral_mtu(peripheral) - 3) return BLE_VALUE_TOO_LONG;
|
||||
if (value_length > peripheral_mtu(peripheral) - 3) return BLE_VALUE_TOO_LONG;
|
||||
if (!l2cap_can_send_fixed_channel_packet_now(peripheral->handle)) return BLE_PERIPHERAL_BUSY;
|
||||
|
||||
peripheral->subclient_id = gatt_client_id;
|
||||
|
209
ble/sm.c
209
ble/sm.c
@ -964,6 +964,72 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
||||
}
|
||||
}
|
||||
|
||||
static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
|
||||
int le_db_index = -1;
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){
|
||||
// lookup device based on IRK
|
||||
int i;
|
||||
for (i=0; i < le_device_db_count(); i++){
|
||||
sm_key_t irk;
|
||||
bd_addr_t address;
|
||||
int address_type;
|
||||
le_device_db_info(i, &address_type, address, irk);
|
||||
if (memcmp(irk, setup->sm_peer_irk, 16) == 0){
|
||||
log_info("sm: device found for IRK, updating");
|
||||
le_db_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if not found, add to db
|
||||
if (le_db_index < 0) {
|
||||
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
|
||||
}
|
||||
}
|
||||
|
||||
// if no IRK available, lookup via public address if possible
|
||||
log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address));
|
||||
if (le_db_index < 0 && setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC){
|
||||
int i;
|
||||
for (i=0; i < le_device_db_count(); i++){
|
||||
bd_addr_t address;
|
||||
int address_type;
|
||||
le_device_db_info(i, &address_type, address, NULL);
|
||||
log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address));
|
||||
if (address_type == BD_ADDR_TYPE_LE_PUBLIC && memcmp(address, setup->sm_peer_address, 6) == 0){
|
||||
log_info("sm: device found for public address, updating");
|
||||
le_db_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if not found, add to db
|
||||
if (le_db_index < 0) {
|
||||
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
|
||||
}
|
||||
}
|
||||
|
||||
if (le_db_index >= 0){
|
||||
le_device_db_local_counter_set(le_db_index, 0);
|
||||
|
||||
// store CSRK
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
||||
log_info("sm: store remote CSRK");
|
||||
le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk);
|
||||
le_device_db_remote_counter_set(le_db_index, 0);
|
||||
}
|
||||
|
||||
// store encryption information
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION
|
||||
&& setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION){
|
||||
log_info("sm: set encryption information (key size %u, authenticatd %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
|
||||
le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
|
||||
sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
// keep le_db_index
|
||||
sm_conn->sm_le_db_index = le_db_index;
|
||||
}
|
||||
|
||||
static void sm_run(void){
|
||||
|
||||
linked_list_iterator_t it;
|
||||
@ -1457,8 +1523,14 @@ static void sm_run(void){
|
||||
|
||||
// keys are sent
|
||||
if (connection->sm_role){
|
||||
// slave -> receive master keys
|
||||
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
// slave -> receive master keys if any
|
||||
if (sm_key_distribution_all_received(connection)){
|
||||
sm_key_distribution_handle_all_received(connection);
|
||||
connection->sm_engine_state = SM_RESPONDER_IDLE;
|
||||
sm_done_for_handle(connection->sm_handle);
|
||||
} else {
|
||||
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
}
|
||||
} else {
|
||||
// master -> all done
|
||||
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
|
||||
@ -1621,7 +1693,19 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
case SM_PH3_CSRK_W4_ENC:
|
||||
swap128(data, setup->sm_local_csrk);
|
||||
log_key("csrk", setup->sm_local_csrk);
|
||||
connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
|
||||
if (setup->sm_key_distribution_send_set){
|
||||
connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
|
||||
} else {
|
||||
// no keys to send, just continue
|
||||
if (connection->sm_role){
|
||||
// slave -> receive master keys
|
||||
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
} else {
|
||||
// master -> all done
|
||||
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
|
||||
sm_done_for_handle(connection->sm_handle);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case SM_RESPONDER_PH4_LTK_W4_ENC:
|
||||
swap128(data, setup->sm_ltk);
|
||||
@ -1835,7 +1919,13 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
|
||||
} else {
|
||||
// master
|
||||
sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
if (sm_key_distribution_all_received(sm_conn)){
|
||||
// skip receiving keys as there are none
|
||||
sm_key_distribution_handle_all_received(sm_conn);
|
||||
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
|
||||
} else {
|
||||
sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -2131,69 +2221,8 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
||||
}
|
||||
// done with key distribution?
|
||||
if (sm_key_distribution_all_received(sm_conn)){
|
||||
int le_db_index = -1;
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){
|
||||
// lookup device based on IRK
|
||||
int i;
|
||||
for (i=0; i < le_device_db_count(); i++){
|
||||
sm_key_t irk;
|
||||
bd_addr_t address;
|
||||
int address_type;
|
||||
le_device_db_info(i, &address_type, address, irk);
|
||||
if (memcmp(irk, setup->sm_peer_irk, 16) == 0){
|
||||
log_info("sm: device found for IRK, updating");
|
||||
le_db_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if not found, add to db
|
||||
if (le_db_index < 0) {
|
||||
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
|
||||
}
|
||||
}
|
||||
|
||||
// if no IRK available, lookup via public address if possible
|
||||
log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address));
|
||||
if (le_db_index < 0 && setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC){
|
||||
int i;
|
||||
for (i=0; i < le_device_db_count(); i++){
|
||||
bd_addr_t address;
|
||||
int address_type;
|
||||
le_device_db_info(i, &address_type, address, NULL);
|
||||
log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address));
|
||||
if (address_type == BD_ADDR_TYPE_LE_PUBLIC && memcmp(address, setup->sm_peer_address, 6) == 0){
|
||||
log_info("sm: device found for public address, updating");
|
||||
le_db_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if not found, add to db
|
||||
if (le_db_index < 0) {
|
||||
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
|
||||
}
|
||||
}
|
||||
|
||||
if (le_db_index >= 0){
|
||||
le_device_db_local_counter_set(le_db_index, 0);
|
||||
|
||||
// store CSRK
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
||||
log_info("sm: store remote CSRK");
|
||||
le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk);
|
||||
le_device_db_remote_counter_set(le_db_index, 0);
|
||||
}
|
||||
|
||||
// store encryption information
|
||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION
|
||||
&& setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION){
|
||||
log_info("sm: set encryption information (key size %u, authenticatd %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
|
||||
le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
|
||||
sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
// keep le_db_index
|
||||
sm_conn->sm_le_db_index = le_db_index;
|
||||
sm_key_distribution_handle_all_received(sm_conn);
|
||||
|
||||
if (sm_conn->sm_role){
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
|
||||
@ -2257,23 +2286,6 @@ void sm_test_set_irk(sm_key_t irk){
|
||||
sm_persistent_irk_ready = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Trigger Security Request
|
||||
*/
|
||||
void sm_send_security_request(uint16_t handle){
|
||||
sm_connection_t * sm_conn = sm_get_connection_for_handle(handle);
|
||||
switch (sm_conn->sm_engine_state){
|
||||
case SM_GENERAL_IDLE:
|
||||
case SM_RESPONDER_IDLE:
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
||||
sm_run();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sm_init(void){
|
||||
// set some (BTstack default) ER and IR
|
||||
int i;
|
||||
@ -2344,16 +2356,35 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres
|
||||
return sm_conn->sm_connection_authorization_state;
|
||||
}
|
||||
|
||||
// request authorization
|
||||
void sm_request_authorization(uint8_t addr_type, bd_addr_t address){
|
||||
static void sm_send_security_request_for_connection(sm_connection_t * sm_conn){
|
||||
switch (sm_conn->sm_engine_state){
|
||||
case SM_GENERAL_IDLE:
|
||||
case SM_RESPONDER_IDLE:
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
||||
sm_run();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger Security Request
|
||||
*/
|
||||
void sm_send_security_request(uint16_t handle){
|
||||
sm_connection_t * sm_conn = sm_get_connection_for_handle(handle);
|
||||
if (!sm_conn) return;
|
||||
sm_send_security_request_for_connection(sm_conn);
|
||||
}
|
||||
|
||||
// request pairing
|
||||
void sm_request_pairing(uint8_t addr_type, bd_addr_t address){
|
||||
sm_connection_t * sm_conn = sm_get_connection(addr_type, address);
|
||||
if (!sm_conn) return; // wrong connection
|
||||
|
||||
log_info("sm_request_authorization in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
|
||||
log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
|
||||
if (sm_conn->sm_role){
|
||||
// code has no effect so far - what's the difference between sm_send_security_request and this in slave role
|
||||
sm_conn->sm_connection_authorization_state = AUTHORIZATION_PENDING;
|
||||
sm_notify_client(SM_AUTHORIZATION_REQUEST, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, 0, 0);
|
||||
sm_send_security_request_for_connection(sm_conn);
|
||||
} else {
|
||||
// used as a trigger to start central/master/initiator security procedures
|
||||
uint16_t ediv;
|
||||
|
2
ble/sm.h
2
ble/sm.h
@ -242,7 +242,7 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres
|
||||
* @brief Used by att_server.c to request user authorization.
|
||||
* @param addr_type and address
|
||||
*/
|
||||
void sm_request_authorization(uint8_t addr_type, bd_addr_t address);
|
||||
void sm_request_pairing(uint8_t addr_type, bd_addr_t address);
|
||||
|
||||
/**
|
||||
* @brief Report user authorization decline.
|
||||
|
@ -88,8 +88,8 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres
|
||||
return AUTHORIZATION_DECLINED;
|
||||
}
|
||||
|
||||
// request authorization
|
||||
void sm_request_authorization(uint8_t addr_type, bd_addr_t address){}
|
||||
// request pairing
|
||||
void sm_request_pairing(uint8_t addr_type, bd_addr_t address){}
|
||||
|
||||
// called by client app on authorization request
|
||||
void sm_authorization_decline(uint8_t addr_type, bd_addr_t address){}
|
||||
|
@ -6,6 +6,7 @@ SUBDIRS = \
|
||||
ble_client \
|
||||
des_iterator \
|
||||
gatt_client \
|
||||
hfp \
|
||||
linked_list \
|
||||
remote_device_db \
|
||||
sdp_client \
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define ENABLE_LOG_DEBUG
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define HAVE_HCI_DUMP
|
||||
|
||||
#define HAVE_SDP_EXTRA_QUERIES
|
||||
#define USE_POSIX_RUN_LOOP
|
||||
@ -32,6 +33,13 @@
|
||||
#define MAX_NO_WHITELIST_ENTRIES 1
|
||||
#define HAVE_MALLOC
|
||||
|
||||
#if 0
|
||||
// DeLock 4.0 Dongle (Broadcom BCM20702A0)
|
||||
#define USB_VENDOR_ID 0x0a5c
|
||||
#define USB_PRODUCT_ID 0x21e8
|
||||
|
||||
#else
|
||||
// Generic CSR 4.0 Dongle
|
||||
// #define USB_VENDOR_ID 0x0a12
|
||||
// #define USB_PRODUCT_ID 0x0001
|
||||
#endif
|
||||
|
@ -53,3 +53,7 @@ hfp_ag_parser_test: ${COMMON_OBJ} hfp_ag.o hfp.o hfp_ag_parser_test.c
|
||||
|
||||
hfp_hf_parser_test: ${COMMON_OBJ} hfp_hf.o hfp.o hfp_hf_parser_test.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
test: all
|
||||
./hfp_ag_parser_test
|
||||
./hfp_hf_parser_test
|
||||
|
@ -77,6 +77,7 @@ typedef enum {
|
||||
CENTRAL_W4_NAME_VALUE,
|
||||
CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE,
|
||||
CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE,
|
||||
CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE
|
||||
} central_state_t;
|
||||
|
||||
typedef struct advertising_report {
|
||||
@ -99,7 +100,8 @@ static int gap_connectable = 0;
|
||||
static char * sm_io_capabilities = NULL;
|
||||
static int sm_mitm_protection = 0;
|
||||
static int sm_have_oob_data = 0;
|
||||
static uint8_t * sm_oob_data = (uint8_t *) "0123456789012345"; // = { 0x30...0x39, 0x30..0x35}
|
||||
static uint8_t * sm_oob_data_A = (uint8_t *) "0123456789012345"; // = { 0x30...0x39, 0x30..0x35}
|
||||
static uint8_t * sm_oob_data_B = (uint8_t *) "3333333333333333"; // = { 0x30...0x39, 0x30..0x35}
|
||||
static int sm_min_key_size = 7;
|
||||
static uint8_t pts_privacy_flag;
|
||||
|
||||
@ -118,10 +120,17 @@ static int current_pts_address_type;
|
||||
static int reconnection_address_set = 0;
|
||||
static bd_addr_t our_private_address;
|
||||
|
||||
static uint16_t pts_signed_write_characteristic_uuid = 0xb00d;
|
||||
static uint16_t pts_signed_write_characteristic_handle = 0x0100;
|
||||
static uint8_t signed_write_value[] = { 0x12 };
|
||||
static int le_device_db_index;
|
||||
static sm_key_t signing_csrk;
|
||||
|
||||
static central_state_t central_state = CENTRAL_IDLE;
|
||||
static le_characteristic_t gap_name_characteristic;
|
||||
static le_characteristic_t gap_reconnection_address_characteristic;
|
||||
static le_characteristic_t gap_peripheral_privacy_flag_characteristic;
|
||||
static le_characteristic_t signed_write_characteristic;
|
||||
|
||||
static void show_usage();
|
||||
///
|
||||
@ -296,10 +305,11 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet,
|
||||
break;
|
||||
|
||||
case SM_IDENTITY_RESOLVING_SUCCEEDED:
|
||||
// skip already detected pts
|
||||
if (memcmp( ((sm_event_t*) packet)->address, current_pts_address, 6) == 0) break;
|
||||
memcpy(current_pts_address, ((sm_event_t*) packet)->address, 6);
|
||||
current_pts_address_type = ((sm_event_t*) packet)->addr_type;
|
||||
le_device_db_index = ((sm_event_t*) packet)->le_device_db_index;
|
||||
// skip already detected pts
|
||||
if (memcmp( ((sm_event_t*) packet)->address, current_pts_address, 6) == 0) break;
|
||||
printf("Address resolving succeeded: resolvable address %s, addr type %u\n",
|
||||
bd_addr_to_str(current_pts_address), current_pts_address_type);
|
||||
break;
|
||||
@ -368,15 +378,15 @@ void handle_gatt_client_event(le_event_t * event){
|
||||
printf("Peripheral Privacy Flag set to TRUE\n");
|
||||
gatt_client_write_value_of_characteristic(gc_id, handle, gap_peripheral_privacy_flag_characteristic.value_handle, 1, &pts_privacy_flag);
|
||||
break;
|
||||
case 2:
|
||||
printf("Signed write on Peripheral Privacy Flag to TRUE\n");
|
||||
pts_privacy_flag = 1;
|
||||
gatt_client_signed_write_without_response(gc_id, handle, gap_peripheral_privacy_flag_characteristic.value_handle, 1, &pts_privacy_flag);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE:
|
||||
printf("Signed write on Characteristic with UUID 0x%04x\n", pts_signed_write_characteristic_uuid);
|
||||
gatt_client_signed_write_without_response(gc_id, handle, signed_write_characteristic.value_handle, sizeof(signed_write_value), signed_write_value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -394,6 +404,11 @@ void handle_gatt_client_event(le_event_t * event){
|
||||
case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE:
|
||||
gap_peripheral_privacy_flag_characteristic = ((le_characteristic_event_t *) event)->characteristic;
|
||||
printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle);
|
||||
break;
|
||||
case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE:
|
||||
signed_write_characteristic = ((le_characteristic_event_t *) event)->characteristic;
|
||||
printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -418,8 +433,19 @@ void show_usage(void){
|
||||
printf("IUT: addr type %u, addr %s\n", iut_address_type, bd_addr_to_str(iut_address));
|
||||
printf("--------------------------\n");
|
||||
printf("GAP: connectable %u, bondable %u\n", gap_connectable, gap_bondable);
|
||||
printf("SM: %s, MITM protection %u, OOB data %u, key range [%u..16]\n",
|
||||
sm_io_capabilities, sm_mitm_protection, sm_have_oob_data, sm_min_key_size);
|
||||
printf("SM: %s, MITM protection %u, key range [%u..16], OOB data: ",
|
||||
sm_io_capabilities, sm_mitm_protection, sm_min_key_size);
|
||||
switch (sm_have_oob_data){
|
||||
case 1:
|
||||
printf_hexdump(sm_oob_data_A, 16);
|
||||
break;
|
||||
case 2:
|
||||
printf_hexdump(sm_oob_data_B, 16);
|
||||
break;
|
||||
default:
|
||||
printf ("None\n");
|
||||
break;
|
||||
}
|
||||
printf("Privacy %u\n", gap_privacy);
|
||||
printf("Device name: %s\n", gap_device_name);
|
||||
// printf("Value Handle: %x\n", value_handle);
|
||||
@ -440,7 +466,8 @@ void show_usage(void){
|
||||
printf("t - terminate connection, stop connecting\n");
|
||||
printf("p - auto connect to PTS\n");
|
||||
printf("P - direct connect to PTS\n");
|
||||
printf("w - signed write on Privacy Flag\n");
|
||||
printf("w - signed write on characteristic with UUID %04x\n", pts_signed_write_characteristic_uuid);
|
||||
printf("W - signed write on attribute with handle 0x%04x and value 0x12\n", pts_signed_write_characteristic_handle);
|
||||
printf("z - Update L2CAP Connection Parameters\n");
|
||||
printf("---\n");
|
||||
printf("4 - IO_CAPABILITY_DISPLAY_ONLY\n");
|
||||
@ -449,6 +476,8 @@ void show_usage(void){
|
||||
printf("7 - IO_CAPABILITY_KEYBOARD_ONLY\n");
|
||||
printf("8 - IO_CAPABILITY_KEYBOARD_DISPLAY\n");
|
||||
printf("m/M - MITM protection off\n");
|
||||
printf("x/X - encryption key range [7..16]/[16..16]\n");
|
||||
printf("y/Y - OOB data off/on/toggle A/B\n");
|
||||
printf("---\n");
|
||||
printf("Ctrl-c - exit\n");
|
||||
printf("---\n");
|
||||
@ -466,20 +495,36 @@ void update_auth_req(void){
|
||||
sm_set_authentication_requirements(auth_req);
|
||||
}
|
||||
|
||||
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
|
||||
int value_length = sizeof(signed_write_value);
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * request = l2cap_get_outgoing_buffer();
|
||||
request[0] = ATT_SIGNED_WRITE_COMMAND;
|
||||
bt_store_16(request, 1, pts_signed_write_characteristic_handle);
|
||||
memcpy(&request[3], signed_write_value, value_length);
|
||||
bt_store_32(request, 3 + value_length, 0);
|
||||
swap64(hash, &request[3 + value_length + 4]);
|
||||
l2cap_send_prepared_connectionless(handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
|
||||
}
|
||||
|
||||
int stdin_process(struct data_source *ds){
|
||||
char buffer;
|
||||
read(ds->fd, &buffer, 1);
|
||||
int res;
|
||||
|
||||
|
||||
// passkey input
|
||||
if (ui_digits_for_passkey){
|
||||
if (buffer < '0' || buffer > '9') return 0;
|
||||
if (buffer < '0' || buffer > '9') {
|
||||
printf("stdinprocess: invalid input 0x%02x\n", buffer);
|
||||
return 0;
|
||||
}
|
||||
printf("%c", buffer);
|
||||
fflush(stdout);
|
||||
ui_passkey = ui_passkey * 10 + buffer - '0';
|
||||
ui_digits_for_passkey--;
|
||||
if (ui_digits_for_passkey == 0){
|
||||
printf("\nSending Passkey '%06x'\n", ui_passkey);
|
||||
printf("\nSending Passkey %u (0x%x)\n", ui_passkey, ui_passkey);
|
||||
sm_passkey_input(peer_addr_type, peer_address, ui_passkey);
|
||||
}
|
||||
return 0;
|
||||
@ -537,16 +582,18 @@ int stdin_process(struct data_source *ds){
|
||||
show_usage();
|
||||
break;
|
||||
case 'b':
|
||||
sm_request_authorization(current_pts_address_type, current_pts_address);
|
||||
sm_request_pairing(current_pts_address_type, current_pts_address);
|
||||
break;
|
||||
case 'c':
|
||||
gap_connectable = 0;
|
||||
update_advertisment_params();
|
||||
hci_connectable_control(gap_connectable);
|
||||
show_usage();
|
||||
break;
|
||||
case 'C':
|
||||
gap_connectable = 1;
|
||||
update_advertisment_params();
|
||||
hci_connectable_control(gap_connectable);
|
||||
show_usage();
|
||||
break;
|
||||
case 'd':
|
||||
@ -616,8 +663,35 @@ int stdin_process(struct data_source *ds){
|
||||
break;
|
||||
case 'w':
|
||||
pts_privacy_flag = 2;
|
||||
central_state = CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE;
|
||||
gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_PERIPHERAL_PRIVACY_FLAG);
|
||||
central_state = CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE;
|
||||
gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, pts_signed_write_characteristic_uuid);
|
||||
break;
|
||||
case 'W':
|
||||
// fetch csrk
|
||||
le_device_db_csrk_get(le_device_db_index, signing_csrk);
|
||||
// calc signature
|
||||
sm_cmac_start(signing_csrk, ATT_SIGNED_WRITE_COMMAND, pts_signed_write_characteristic_handle, sizeof(signed_write_value), signed_write_value, 0, att_signed_write_handle_cmac_result);
|
||||
break;
|
||||
case 'x':
|
||||
sm_min_key_size = 7;
|
||||
sm_set_encryption_key_size_range(7, 16);
|
||||
show_usage();
|
||||
break;
|
||||
case 'X':
|
||||
sm_min_key_size = 16;
|
||||
sm_set_encryption_key_size_range(16, 16);
|
||||
show_usage();
|
||||
break; case 'y':
|
||||
sm_have_oob_data = 0;
|
||||
show_usage();
|
||||
break;
|
||||
case 'Y':
|
||||
if (sm_have_oob_data){
|
||||
sm_have_oob_data = 3 - sm_have_oob_data;
|
||||
} else {
|
||||
sm_have_oob_data = 1;
|
||||
}
|
||||
show_usage();
|
||||
break;
|
||||
case 'z':
|
||||
printf("Updating l2cap connection parameters\n");
|
||||
@ -632,12 +706,18 @@ int stdin_process(struct data_source *ds){
|
||||
}
|
||||
|
||||
static int get_oob_data_callback(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_data){
|
||||
if(!sm_have_oob_data) return 0;
|
||||
memcpy(oob_data, sm_oob_data, 16);
|
||||
return 1;
|
||||
switch(sm_have_oob_data){
|
||||
case 1:
|
||||
memcpy(oob_data, sm_oob_data_A, 16);
|
||||
return 1;
|
||||
case 2:
|
||||
memcpy(oob_data, sm_oob_data_B, 16);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
@ -709,7 +789,7 @@ int btstack_main(int argc, const char * argv[]){
|
||||
current_pts_address_type = public_pts_address_type;
|
||||
|
||||
// classic discoverable / connectable
|
||||
hci_connectable_control(1);
|
||||
hci_connectable_control(0);
|
||||
hci_discoverable_control(1);
|
||||
|
||||
// allow foor terminal input
|
||||
|
@ -33,6 +33,7 @@ uint8_t * mock_packet_buffer(void){
|
||||
|
||||
void mock_clear_packet_buffer(void){
|
||||
packet_buffer_len = 0;
|
||||
memset(packet_buffer, 0, sizeof(packet_buffer));
|
||||
}
|
||||
|
||||
static void dump_packet(int packet_type, uint8_t * buffer, uint16_t size){
|
||||
|
@ -118,6 +118,49 @@ uint16_t mock_packet_buffer_len(void);
|
||||
void mock_clear_packet_buffer(void);
|
||||
|
||||
|
||||
void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
uint16_t aHandle;
|
||||
sm_event_t * sm_event;
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (packet[0]) {
|
||||
case SM_PASSKEY_INPUT_NUMBER:
|
||||
// store peer address for input
|
||||
sm_event = (sm_event_t *) packet;
|
||||
printf("\nGAP Bonding %s (%u): Enter 6 digit passkey: '", bd_addr_to_str(sm_event->address), sm_event->addr_type);
|
||||
fflush(stdout);
|
||||
break;
|
||||
|
||||
case SM_PASSKEY_DISPLAY_NUMBER:
|
||||
sm_event = (sm_event_t *) packet;
|
||||
printf("\nGAP Bonding %s (%u): Display Passkey '%06u\n", bd_addr_to_str(sm_event->address), sm_event->addr_type, sm_event->passkey);
|
||||
break;
|
||||
|
||||
case SM_PASSKEY_DISPLAY_CANCEL:
|
||||
sm_event = (sm_event_t *) packet;
|
||||
printf("\nGAP Bonding %s (%u): Display cancel\n", bd_addr_to_str(sm_event->address), sm_event->addr_type);
|
||||
break;
|
||||
|
||||
case SM_JUST_WORKS_REQUEST:
|
||||
// auto-authorize connection if requested
|
||||
sm_event = (sm_event_t *) packet;
|
||||
sm_just_works_confirm(sm_event->addr_type, sm_event->address);
|
||||
printf("Just Works request confirmed\n");
|
||||
break;
|
||||
|
||||
case SM_AUTHORIZATION_REQUEST:
|
||||
// auto-authorize connection if requested
|
||||
sm_event = (sm_event_t *) packet;
|
||||
sm_authorization_grant(sm_event->addr_type, sm_event->address);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
|
||||
int i;
|
||||
for (i=0; i<size; i++){
|
||||
@ -141,6 +184,7 @@ TEST_GROUP(SecurityManager){
|
||||
sm_init();
|
||||
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
|
||||
sm_set_authentication_requirements( SM_AUTHREQ_BONDING );
|
||||
sm_register_packet_handler(app_packet_handler);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user