Merge branch 'develop' of https://github.com/bluekitchen/btstack into develop

This commit is contained in:
Matthias Ringwald 2017-01-13 19:27:31 +01:00
commit e1cd7dec93
5 changed files with 49 additions and 15 deletions

View File

@ -76,6 +76,7 @@ ENABLE_LOG_INTO_HCI_DUMP | Log debug messages as part of packet log
ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (only CC256x/WL18xx and USB CSR controllers)
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections using [mbed TLS library](https://tls.mbed.org)
ENABLE_LE_DATA_CHANNELS | Enable LE Data Channels in credit-based flow control mode
ENABLE_LE_SIGNED_WRITE | Enable LE Signed Writes in ATT/GATT
### Memory configuration directives {#sec:memoryConfigurationHowTo}

View File

@ -1120,9 +1120,11 @@ uint16_t att_handle_request(att_connection_t * att_connection,
case ATT_WRITE_COMMAND:
handle_write_command(att_connection, request_buffer, request_len, response_buffer, response_buffer_size);
break;
#ifdef ENABLE_LE_SIGNED_WRITE
case ATT_SIGNED_WRITE_COMMAND:
log_info("handle_signed_write_command preprocessed by att_server.c");
break;
#endif
default:
log_info("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]);
log_info_hexdump(&request_buffer[9], request_len-9);

View File

@ -235,6 +235,7 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
}
}
#ifdef ENABLE_LE_SIGNED_WRITE
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
att_server_t * att_server = att_server_for_state(ATT_SERVER_W4_SIGNED_WRITE_VALIDATION);
@ -255,7 +256,7 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);
}
#endif
// pre: att_server->state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED
// pre: can send now
@ -303,6 +304,7 @@ static int att_server_process_validated_request(att_server_t * att_server){
static void att_run_for_context(att_server_t * att_server){
switch (att_server->state){
case ATT_SERVER_REQUEST_RECEIVED:
#ifdef ENABLE_LE_SIGNED_WRITE
if (att_server->request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){
log_info("ATT Signed Write!");
if (!sm_cmac_ready()) {
@ -344,7 +346,7 @@ static void att_run_for_context(att_server_t * att_server){
sm_cmac_signed_write_start(csrk, att_server->request_buffer[0], attribute_handle, att_server->request_size - 15, &att_server->request_buffer[3], counter_packet, att_signed_write_handle_cmac_result);
return;
}
#endif
// move on
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);

View File

@ -68,7 +68,10 @@ static uint8_t pts_suppress_mtu_exchange;
static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size);
static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code);
#ifdef ENABLE_LE_SIGNED_WRITE
static void att_signed_write_handle_cmac_result(uint8_t hash[8]);
#endif
static uint16_t peripheral_mtu(gatt_client_t *peripheral){
if (peripheral->mtu > l2cap_max_le_mtu()){
@ -275,6 +278,7 @@ static void att_read_multiple_request(uint16_t peripheral_handle, uint16_t num_v
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, offset);
}
#ifdef ENABLE_LE_SIGNED_WRITE
// precondition: can_send_packet_now == TRUE
static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value, uint32_t sign_counter, uint8_t sgn[8]){
l2cap_reserve_packet_buffer();
@ -286,6 +290,7 @@ static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_
reverse_64(sgn, &request[3 + value_length + 4]);
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
}
#endif
// precondition: can_send_packet_now == TRUE
static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){
@ -424,9 +429,11 @@ static void send_gatt_read_characteristic_descriptor_request(gatt_client_t * per
att_read_request(ATT_READ_REQUEST, peripheral->con_handle, peripheral->attribute_handle);
}
#ifdef ENABLE_LE_SIGNED_WRITE
static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t sign_counter){
att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac);
}
#endif
static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
uint8_t attr_length = packet[1];
@ -960,6 +967,7 @@ static void gatt_client_run(void){
send_gatt_execute_write_request(peripheral);
return;
#ifdef ENABLE_LE_SIGNED_WRITE
case P_W4_CMAC_READY:
if (sm_cmac_ready()){
sm_key_t csrk;
@ -982,6 +990,7 @@ static void gatt_client_run(void){
gatt_client_handle_transaction_complete(peripheral);
return;
}
#endif
default:
break;
@ -1346,6 +1355,7 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle,
gatt_client_run();
}
#ifdef ENABLE_LE_SIGNED_WRITE
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &gatt_client_connections);
@ -1377,6 +1387,7 @@ uint8_t gatt_client_signed_write_without_response(btstack_packet_handler_t callb
gatt_client_run();
return 0;
}
#endif
uint8_t gatt_client_discover_primary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);

View File

@ -68,6 +68,10 @@
#include "sm_mbedtls_allocator.h"
#endif
#if defined(ENABLE_LE_SIGNED_WRITE) || defined(ENABLE_LE_SECURE_CONNECTIONS)
#define ENABLE_CMAC_ENGINE
#endif
//
// SM internal types and globals
//
@ -180,6 +184,7 @@ static random_address_update_t rau_state;
static bd_addr_t sm_random_address;
// CMAC Calculation: General
#ifdef ENABLE_CMAC_ENGINE
static cmac_state_t sm_cmac_state;
static uint16_t sm_cmac_message_len;
static sm_key_t sm_cmac_k;
@ -189,11 +194,14 @@ static uint8_t sm_cmac_block_current;
static uint8_t sm_cmac_block_count;
static uint8_t (*sm_cmac_get_byte)(uint16_t offset);
static void (*sm_cmac_done_handler)(uint8_t * hash);
#endif
// CMAC for ATT Signed Writes
#ifdef ENABLE_LE_SIGNED_WRITE
static uint8_t sm_cmac_header[3];
static const uint8_t * sm_cmac_message;
static uint8_t sm_cmac_sign_counter[4];
#endif
// CMAC for Secure Connection functions
#ifdef ENABLE_LE_SECURE_CONNECTIONS
@ -363,7 +371,6 @@ static void sm_done_for_handle(hci_con_handle_t con_handle);
static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle);
static inline int sm_calc_actual_encryption_key_size(int other);
static int sm_validate_stk_generation_method(void);
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data);
static void log_info_hex16(const char * name, uint16_t value){
log_info("%-6s 0x%04x", name, value);
@ -841,17 +848,6 @@ int sm_address_resolution_lookup(uint8_t address_type, bd_addr_t address){
return 0;
}
// CMAC Implementation using AES128 engine
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
int i;
int carry = 0;
for (i=len-1; i >= 0 ; i--){
int new_carry = data[i] >> 7;
data[i] = data[i] << 1 | carry;
carry = new_carry;
}
}
// while x_state++ for an enum is possible in C, it isn't in C++. we use this helpers to avoid compile errors for now
static inline void sm_next_responding_state(sm_connection_t * sm_conn){
sm_conn->sm_engine_state = (security_manager_state_t) (((int)sm_conn->sm_engine_state) + 1);
@ -864,6 +860,7 @@ static inline void rau_next_state(void){
}
// CMAC calculation using AES Engine
#ifdef ENABLE_CMAC_ENGINE
static inline void sm_cmac_next_state(void){
sm_cmac_state = (cmac_state_t) (((int)sm_cmac_state) + 1);
@ -903,8 +900,10 @@ void sm_cmac_general_start(const sm_key_t key, uint16_t message_len, uint8_t (*g
// let's go
sm_run();
}
#endif
// cmac for ATT Message signing
#ifdef ENABLE_LE_SIGNED_WRITE
static uint8_t sm_cmac_signed_write_message_get_byte(uint16_t offset){
if (offset >= sm_cmac_message_len) {
log_error("sm_cmac_signed_write_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_message_len);
@ -933,8 +932,9 @@ void sm_cmac_signed_write_start(const sm_key_t k, uint8_t opcode, hci_con_handle
sm_cmac_message = message;
sm_cmac_general_start(k, total_message_len, &sm_cmac_signed_write_message_get_byte, done_handler);
}
#endif
#ifdef ENABLE_CMAC_ENGINE
static void sm_cmac_handle_aes_engine_ready(void){
switch (sm_cmac_state){
case CMAC_CALC_SUBKEYS: {
@ -973,6 +973,17 @@ static void sm_cmac_handle_aes_engine_ready(void){
}
}
// CMAC Implementation using AES128 engine
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
int i;
int carry = 0;
for (i=len-1; i >= 0 ; i--){
int new_carry = data[i] >> 7;
data[i] = data[i] << 1 | carry;
carry = new_carry;
}
}
static void sm_cmac_handle_encryption_result(sm_key_t data){
switch (sm_cmac_state){
case CMAC_W4_SUBKEYS: {
@ -1034,6 +1045,7 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){
break;
}
}
#endif
static void sm_trigger_user_response(sm_connection_t * sm_conn){
// notify client for: JUST WORKS confirm, Numeric comparison confirm, PASSKEY display or input
@ -1857,6 +1869,7 @@ static void sm_run(void){
break;
}
#ifdef ENABLE_CMAC_ENGINE
// CMAC
switch (sm_cmac_state){
case CMAC_CALC_SUBKEYS:
@ -1869,6 +1882,7 @@ static void sm_run(void){
default:
break;
}
#endif
// CSRK Lookup
// -- if csrk lookup ready, find connection that require csrk lookup
@ -2583,6 +2597,7 @@ static void sm_handle_encryption_result(uint8_t * data){
break;
}
#ifdef ENABLE_CMAC_ENGINE
switch (sm_cmac_state){
case CMAC_W4_SUBKEYS:
case CMAC_W4_MI:
@ -2596,6 +2611,7 @@ static void sm_handle_encryption_result(uint8_t * data){
default:
break;
}
#endif
// retrieve sm_connection provided to sm_aes128_start_encryption
sm_connection_t * connection = (sm_connection_t*) sm_aes128_context;
@ -3635,7 +3651,9 @@ void sm_init(void){
sm_max_encryption_key_size = 16;
sm_min_encryption_key_size = 7;
#ifdef ENABLE_CMAC_ENGINE
sm_cmac_state = CMAC_IDLE;
#endif
dkg_state = DKG_W4_WORKING;
rau_state = RAU_W4_WORKING;
sm_aes128_state = SM_AES128_IDLE;