sm: flip message data before calculating CMAC, also store hash result as little endian

This commit is contained in:
Matthias Ringwald 2015-08-19 22:39:19 +02:00
parent 12e4aa3c16
commit 03679531e4
4 changed files with 25 additions and 16 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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