diff --git a/ble/att_server.c b/ble/att_server.c index aa06a1d5e..d4f701e6d 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -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 (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"); att_server_state = ATT_SERVER_IDLE; return; @@ -268,7 +270,8 @@ static void att_run(void){ att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION; log_info("Orig Signature: "); 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; } // NOTE: fall through for regular commands diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 907c48d0a..52aed181a 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -293,8 +293,7 @@ static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_ bt_store_16(request, 1, attribute_handle); memcpy(&request[3], value, value_length); 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); } @@ -859,7 +858,7 @@ static void gatt_client_run(void){ le_device_db_csrk_get(peripheral->le_device_index, csrk); uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index); 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; diff --git a/ble/sm.c b/ble/sm.c index 82e8dcddc..bea73c6d9 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -144,6 +144,7 @@ static bd_addr_t sm_random_address; // CMAC calculation static cmac_state_t sm_cmac_state; static sm_key_t sm_cmac_k; +static uint8_t sm_cmac_header[3]; static uint16_t sm_cmac_message_len; static uint8_t * sm_cmac_message; 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); return 0; } - int actual_len = sm_cmac_message_len - 4; - if (offset < actual_len) { - return sm_cmac_message[offset]; - } else { - return sm_cmac_sign_counter[offset - actual_len]; + + offset = sm_cmac_message_len - 1 - offset; + + // sm_cmac_header[3] | message[] | sm_cmac_sign_counter[4] + 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); - sm_cmac_message_len = message_len + 4; // incl. virtually appended sign_counter in LE - sm_cmac_message = message; + sm_cmac_header[0] = opcode; + bt_store_16(sm_cmac_header, 1, handle); 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_block_current = 0; memset(sm_cmac_x, 0, 16); @@ -734,8 +743,6 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){ sm_cmac_m_last[i] = k2[i]; } } - log_key("last", sm_cmac_m_last); - // next sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST; diff --git a/ble/sm.h b/ble/sm.h index 41c973a56..9ee6041f9 100644 --- a/ble/sm.h +++ b/ble/sm.h @@ -261,7 +261,7 @@ void sm_authorization_grant(uint8_t addr_type, bd_addr_t address); * @note Message and result are in little endian to allows passing in ATT PDU without flipping them first. */ 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