mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-18 14:42:33 +00:00
Merge branch 'master' of https://github.com/bluekitchen/btstack
This commit is contained in:
commit
7a4980db5e
@ -211,7 +211,9 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
|
|||||||
|
|
||||||
if (att_server_state != ATT_SERVER_W4_SIGNED_WRITE_VALIDATION) return;
|
if (att_server_state != ATT_SERVER_W4_SIGNED_WRITE_VALIDATION) return;
|
||||||
|
|
||||||
if (memcmp(hash, &att_request_buffer[att_request_size-8], 8)){
|
uint8_t hash_flipped[8];
|
||||||
|
swap64(hash, hash_flipped);
|
||||||
|
if (memcmp(hash_flipped, &att_request_buffer[att_request_size-8], 8)){
|
||||||
log_info("ATT Signed Write, invalid signature");
|
log_info("ATT Signed Write, invalid signature");
|
||||||
att_server_state = ATT_SERVER_IDLE;
|
att_server_state = ATT_SERVER_IDLE;
|
||||||
return;
|
return;
|
||||||
@ -268,7 +270,8 @@ static void att_run(void){
|
|||||||
att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION;
|
att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION;
|
||||||
log_info("Orig Signature: ");
|
log_info("Orig Signature: ");
|
||||||
hexdump( &att_request_buffer[att_request_size-8], 8);
|
hexdump( &att_request_buffer[att_request_size-8], 8);
|
||||||
sm_cmac_start(csrk, att_request_size - 12, att_request_buffer, counter_packet, att_signed_write_handle_cmac_result);
|
uint16_t attribute_handle = READ_BT_16(att_request_buffer, 1);
|
||||||
|
sm_cmac_start(csrk, att_request_buffer[0], attribute_handle, att_request_size - 15, &att_request_buffer[3], counter_packet, att_signed_write_handle_cmac_result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// NOTE: fall through for regular commands
|
// NOTE: fall through for regular commands
|
||||||
|
@ -293,8 +293,7 @@ static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_
|
|||||||
bt_store_16(request, 1, attribute_handle);
|
bt_store_16(request, 1, attribute_handle);
|
||||||
memcpy(&request[3], value, value_length);
|
memcpy(&request[3], value, value_length);
|
||||||
bt_store_32(request, 3 + value_length, sign_counter);
|
bt_store_32(request, 3 + value_length, sign_counter);
|
||||||
memcpy(&request[3 + value_length+4], sgn, 8);
|
swap64(sgn, &request[3 + value_length + 4]);
|
||||||
|
|
||||||
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
|
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,7 +858,7 @@ static void gatt_client_run(void){
|
|||||||
le_device_db_csrk_get(peripheral->le_device_index, csrk);
|
le_device_db_csrk_get(peripheral->le_device_index, csrk);
|
||||||
uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
|
uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
|
||||||
peripheral->gatt_client_state = P_W4_CMAC_RESULT;
|
peripheral->gatt_client_state = P_W4_CMAC_RESULT;
|
||||||
sm_cmac_start(csrk, peripheral->attribute_length, peripheral->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
|
sm_cmac_start(csrk, ATT_SIGNED_WRITE_COMMAND, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
62
ble/sm.c
62
ble/sm.c
@ -144,6 +144,7 @@ static bd_addr_t sm_random_address;
|
|||||||
// CMAC calculation
|
// CMAC calculation
|
||||||
static cmac_state_t sm_cmac_state;
|
static cmac_state_t sm_cmac_state;
|
||||||
static sm_key_t sm_cmac_k;
|
static sm_key_t sm_cmac_k;
|
||||||
|
static uint8_t sm_cmac_header[3];
|
||||||
static uint16_t sm_cmac_message_len;
|
static uint16_t sm_cmac_message_len;
|
||||||
static uint8_t * sm_cmac_message;
|
static uint8_t * sm_cmac_message;
|
||||||
static uint8_t sm_cmac_sign_counter[4];
|
static uint8_t sm_cmac_sign_counter[4];
|
||||||
@ -618,19 +619,27 @@ static inline uint8_t sm_cmac_message_get_byte(int offset){
|
|||||||
log_error("sm_cmac_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_message_len);
|
log_error("sm_cmac_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_message_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int actual_len = sm_cmac_message_len - 4;
|
|
||||||
if (offset < actual_len) {
|
offset = sm_cmac_message_len - 1 - offset;
|
||||||
return sm_cmac_message[offset];
|
|
||||||
} else {
|
// sm_cmac_header[3] | message[] | sm_cmac_sign_counter[4]
|
||||||
return sm_cmac_message[offset - actual_len];
|
if (offset < 3){
|
||||||
|
return sm_cmac_header[offset];
|
||||||
}
|
}
|
||||||
|
int actual_message_len_incl_header = sm_cmac_message_len - 4;
|
||||||
|
if (offset < actual_message_len_incl_header){
|
||||||
|
return sm_cmac_message[offset - 3];
|
||||||
|
}
|
||||||
|
return sm_cmac_sign_counter[offset - actual_message_len_incl_header];
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm_cmac_start(sm_key_t k, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8])){
|
void sm_cmac_start(sm_key_t k, uint8_t opcode, uint16_t handle, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8])){
|
||||||
memcpy(sm_cmac_k, k, 16);
|
memcpy(sm_cmac_k, k, 16);
|
||||||
sm_cmac_message_len = message_len + 4; // incl. virtually appended sign_counter in LE
|
sm_cmac_header[0] = opcode;
|
||||||
sm_cmac_message = message;
|
bt_store_16(sm_cmac_header, 1, handle);
|
||||||
bt_store_32(sm_cmac_sign_counter, 0, sign_counter);
|
bt_store_32(sm_cmac_sign_counter, 0, sign_counter);
|
||||||
|
sm_cmac_message_len = 3 + message_len + 4; // incl. virtually prepended att opcode, handle and appended sign_counter in LE
|
||||||
|
sm_cmac_message = message;
|
||||||
sm_cmac_done_handler = done_handler;
|
sm_cmac_done_handler = done_handler;
|
||||||
sm_cmac_block_current = 0;
|
sm_cmac_block_current = 0;
|
||||||
memset(sm_cmac_x, 0, 16);
|
memset(sm_cmac_x, 0, 16);
|
||||||
@ -643,6 +652,8 @@ void sm_cmac_start(sm_key_t k, uint16_t message_len, uint8_t * message, uint32_t
|
|||||||
sm_cmac_block_count = 1;
|
sm_cmac_block_count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_info("sm_cmac_start: len %u, block count %u", sm_cmac_message_len, sm_cmac_block_count);
|
||||||
|
|
||||||
// first, we need to compute l for k1, k2, and m_last
|
// first, we need to compute l for k1, k2, and m_last
|
||||||
sm_cmac_state = CMAC_CALC_SUBKEYS;
|
sm_cmac_state = CMAC_CALC_SUBKEYS;
|
||||||
|
|
||||||
@ -733,7 +744,6 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// next
|
// next
|
||||||
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
|
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
|
||||||
break;
|
break;
|
||||||
@ -916,7 +926,7 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
|||||||
sm_connection = (sm_connection_t *) context;
|
sm_connection = (sm_connection_t *) context;
|
||||||
switch (event){
|
switch (event){
|
||||||
case ADDRESS_RESOLUTION_SUCEEDED:
|
case ADDRESS_RESOLUTION_SUCEEDED:
|
||||||
sm_connection->sm_csrk_lookup_state = CSRK_LOOKUP_SUCCEEDED;
|
sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
|
||||||
sm_connection->sm_le_db_index = matched_device_id;
|
sm_connection->sm_le_db_index = matched_device_id;
|
||||||
log_info("ADDRESS_RESOLUTION_SUCEEDED, index %d", sm_connection->sm_le_db_index);
|
log_info("ADDRESS_RESOLUTION_SUCEEDED, index %d", sm_connection->sm_le_db_index);
|
||||||
if (sm_connection->sm_role) break;
|
if (sm_connection->sm_role) break;
|
||||||
@ -931,7 +941,7 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ADDRESS_RESOLUTION_FAILED:
|
case ADDRESS_RESOLUTION_FAILED:
|
||||||
sm_connection->sm_csrk_lookup_state = CSRK_LOOKUP_FAILED;
|
sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED;
|
||||||
if (sm_connection->sm_role) break;
|
if (sm_connection->sm_role) break;
|
||||||
if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break;
|
if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break;
|
||||||
sm_connection->sm_security_request_received = 0;
|
sm_connection->sm_security_request_received = 0;
|
||||||
@ -1038,10 +1048,10 @@ static void sm_run(void){
|
|||||||
while(linked_list_iterator_has_next(&it)){
|
while(linked_list_iterator_has_next(&it)){
|
||||||
hci_connection_t * hci_connection = (hci_connection_t *) linked_list_iterator_next(&it);
|
hci_connection_t * hci_connection = (hci_connection_t *) linked_list_iterator_next(&it);
|
||||||
sm_connection_t * sm_connection = &hci_connection->sm_connection;
|
sm_connection_t * sm_connection = &hci_connection->sm_connection;
|
||||||
if (sm_connection->sm_csrk_lookup_state == CSRK_LOOKUP_W4_READY){
|
if (sm_connection->sm_irk_lookup_state == IRK_LOOKUP_W4_READY){
|
||||||
// and start lookup
|
// and start lookup
|
||||||
sm_address_resolution_start_lookup(sm_connection->sm_peer_addr_type, sm_connection->sm_peer_address, ADDRESS_RESOLUTION_FOR_CONNECTION, sm_connection);
|
sm_address_resolution_start_lookup(sm_connection->sm_peer_addr_type, sm_connection->sm_peer_address, ADDRESS_RESOLUTION_FOR_CONNECTION, sm_connection);
|
||||||
sm_connection->sm_csrk_lookup_state = CSRK_LOOKUP_STARTED;
|
sm_connection->sm_irk_lookup_state = IRK_LOOKUP_STARTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1428,8 +1438,17 @@ static void sm_run(void){
|
|||||||
}
|
}
|
||||||
if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
||||||
setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
|
setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
|
||||||
|
|
||||||
uint8_t buffer[17];
|
uint8_t buffer[17];
|
||||||
buffer[0] = SM_CODE_SIGNING_INFORMATION;
|
buffer[0] = SM_CODE_SIGNING_INFORMATION;
|
||||||
|
// optimization: use CSRK of Peripheral if received, to avoid storing two CSRKs in our DB
|
||||||
|
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
||||||
|
log_info("sm: mirror CSRK");
|
||||||
|
memcpy(setup->sm_local_csrk, setup->sm_peer_csrk, 16);
|
||||||
|
} else {
|
||||||
|
log_info("sm: store local CSRK");
|
||||||
|
le_device_db_csrk_set(connection->sm_le_db_index, setup->sm_local_csrk);
|
||||||
|
}
|
||||||
swap128(setup->sm_local_csrk, &buffer[1]);
|
swap128(setup->sm_local_csrk, &buffer[1]);
|
||||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||||
sm_timeout_reset(connection);
|
sm_timeout_reset(connection);
|
||||||
@ -1744,7 +1763,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
sm_conn->sm_le_db_index = -1;
|
sm_conn->sm_le_db_index = -1;
|
||||||
|
|
||||||
// prepare CSRK lookup (does not involve setup)
|
// prepare CSRK lookup (does not involve setup)
|
||||||
sm_conn->sm_csrk_lookup_state = CSRK_LOOKUP_W4_READY;
|
sm_conn->sm_irk_lookup_state = IRK_LOOKUP_W4_READY;
|
||||||
|
|
||||||
// just connected -> everything else happens in sm_run()
|
// just connected -> everything else happens in sm_run()
|
||||||
if (sm_conn->sm_role){
|
if (sm_conn->sm_role){
|
||||||
@ -1954,11 +1973,11 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
sm_pdu_received_in_wrong_state(sm_conn);
|
sm_pdu_received_in_wrong_state(sm_conn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sm_conn->sm_csrk_lookup_state == CSRK_LOOKUP_FAILED){
|
if (sm_conn->sm_irk_lookup_state == IRK_LOOKUP_FAILED){
|
||||||
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sm_conn->sm_csrk_lookup_state == CSRK_LOOKUP_SUCCEEDED){
|
if (sm_conn->sm_irk_lookup_state == IRK_LOOKUP_SUCCEEDED){
|
||||||
uint16_t ediv;
|
uint16_t ediv;
|
||||||
le_device_db_encryption_get(sm_conn->sm_le_db_index, &ediv, NULL, NULL, NULL, NULL, NULL);
|
le_device_db_encryption_get(sm_conn->sm_le_db_index, &ediv, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (ediv){
|
if (ediv){
|
||||||
@ -2155,7 +2174,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
|
|
||||||
// store CSRK
|
// store CSRK
|
||||||
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
|
||||||
log_info("sm: set csrk");
|
log_info("sm: store remote CSRK");
|
||||||
le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk);
|
le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk);
|
||||||
le_device_db_remote_counter_set(le_db_index, 0);
|
le_device_db_remote_counter_set(le_db_index, 0);
|
||||||
}
|
}
|
||||||
@ -2169,6 +2188,9 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keep le_db_index
|
||||||
|
sm_conn->sm_le_db_index = le_db_index;
|
||||||
|
|
||||||
if (sm_conn->sm_role){
|
if (sm_conn->sm_role){
|
||||||
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
|
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
|
||||||
sm_done_for_handle(sm_conn->sm_handle);
|
sm_done_for_handle(sm_conn->sm_handle);
|
||||||
@ -2332,11 +2354,11 @@ void sm_request_authorization(uint8_t addr_type, bd_addr_t address){
|
|||||||
// used as a trigger to start central/master/initiator security procedures
|
// used as a trigger to start central/master/initiator security procedures
|
||||||
uint16_t ediv;
|
uint16_t ediv;
|
||||||
if (sm_conn->sm_engine_state == SM_INITIATOR_CONNECTED){
|
if (sm_conn->sm_engine_state == SM_INITIATOR_CONNECTED){
|
||||||
switch (sm_conn->sm_csrk_lookup_state){
|
switch (sm_conn->sm_irk_lookup_state){
|
||||||
case CSRK_LOOKUP_FAILED:
|
case IRK_LOOKUP_FAILED:
|
||||||
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||||
break;
|
break;
|
||||||
case CSRK_LOOKUP_SUCCEEDED:
|
case IRK_LOOKUP_SUCCEEDED:
|
||||||
le_device_db_encryption_get(sm_conn->sm_le_db_index, &ediv, NULL, NULL, NULL, NULL, NULL);
|
le_device_db_encryption_get(sm_conn->sm_le_db_index, &ediv, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (ediv){
|
if (ediv){
|
||||||
log_info("sm: Setting up previous ltk/ediv/rand for device index %u", sm_conn->sm_le_db_index);
|
log_info("sm: Setting up previous ltk/ediv/rand for device index %u", sm_conn->sm_le_db_index);
|
||||||
|
5
ble/sm.h
5
ble/sm.h
@ -258,10 +258,11 @@ void sm_authorization_grant(uint8_t addr_type, bd_addr_t address);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Support for signed writes, used by att_server.
|
* @brief Support for signed writes, used by att_server.
|
||||||
* @note Message and result are in little endian to allows passing in ATT PDU without flipping them first.
|
* @note Message and result are in little endian to allows passing in ATT PDU without flipping.
|
||||||
|
* @note calculated hash in done_callback is big endian
|
||||||
*/
|
*/
|
||||||
int sm_cmac_ready(void);
|
int sm_cmac_ready(void);
|
||||||
void sm_cmac_start(sm_key_t k, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8]));
|
void sm_cmac_start(sm_key_t k, uint8_t opcode, uint16_t attribute_handle, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8]));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Match address against bonded devices
|
* @brief Match address against bonded devices
|
||||||
|
14
src/hci.h
14
src/hci.h
@ -435,12 +435,12 @@ typedef enum {
|
|||||||
} security_manager_state_t;
|
} security_manager_state_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CSRK_LOOKUP_IDLE,
|
IRK_LOOKUP_IDLE,
|
||||||
CSRK_LOOKUP_W4_READY,
|
IRK_LOOKUP_W4_READY,
|
||||||
CSRK_LOOKUP_STARTED,
|
IRK_LOOKUP_STARTED,
|
||||||
CSRK_LOOKUP_SUCCEEDED,
|
IRK_LOOKUP_SUCCEEDED,
|
||||||
CSRK_LOOKUP_FAILED
|
IRK_LOOKUP_FAILED
|
||||||
} csrk_lookup_state_t;
|
} irk_lookup_state_t;
|
||||||
|
|
||||||
// Authorization state
|
// Authorization state
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -469,7 +469,7 @@ typedef struct sm_connection {
|
|||||||
uint8_t sm_peer_addr_type;
|
uint8_t sm_peer_addr_type;
|
||||||
bd_addr_t sm_peer_address;
|
bd_addr_t sm_peer_address;
|
||||||
security_manager_state_t sm_engine_state;
|
security_manager_state_t sm_engine_state;
|
||||||
csrk_lookup_state_t sm_csrk_lookup_state;
|
irk_lookup_state_t sm_irk_lookup_state;
|
||||||
uint8_t sm_connection_encrypted;
|
uint8_t sm_connection_encrypted;
|
||||||
uint8_t sm_connection_authenticated; // [0..1]
|
uint8_t sm_connection_authenticated; // [0..1]
|
||||||
uint8_t sm_actual_encryption_key_size;
|
uint8_t sm_actual_encryption_key_size;
|
||||||
|
3
test/pts/packetlogger.sh
Executable file
3
test/pts/packetlogger.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
killall PacketLogger
|
||||||
|
open /tmp/hci_dump.pklg
|
Loading…
x
Reference in New Issue
Block a user