From d2d764240dd2166dedd1bc9caa6111339c0f291c Mon Sep 17 00:00:00 2001 From: "matthias.ringwald@gmail.com" <matthias.ringwald@gmail.com@1a0a8af8-31b5-11de-8e0c-53a27eea117e> Date: Mon, 2 Mar 2015 21:12:29 +0000 Subject: [PATCH] add encryption info to central db --- ble/att_server.c | 6 ++-- ble/central_device_db.h | 50 +++++++++++++++++++++++++++++---- ble/central_device_db_dummy.c | 34 ++++++++++++++++++++--- ble/central_device_db_memory.c | 51 +++++++++++++++++++++++++++++----- ble/sm.c | 35 +++++++++++++++++------ 5 files changed, 149 insertions(+), 27 deletions(-) diff --git a/ble/att_server.c b/ble/att_server.c index 2bb3319d6..f98c668ed 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -203,7 +203,7 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){ // update sequence number uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12); - central_device_db_counter_set(att_ir_central_device_db_index, counter_packet+1); + central_device_db_remote_counter_set(att_ir_central_device_db_index, counter_packet+1); att_server_state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED; att_run(); } @@ -237,7 +237,7 @@ static void att_run(void){ // check counter uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12); - uint32_t counter_db = central_device_db_counter_get(att_ir_central_device_db_index); + uint32_t counter_db = central_device_db_remote_counter_get(att_ir_central_device_db_index); log_info("ATT Signed Write, DB counter %u, packet counter %u", counter_db, counter_packet); if (counter_packet < counter_db){ log_info("ATT Signed Write, db reports higher counter, abort"); @@ -247,7 +247,7 @@ static void att_run(void){ // signature is { sequence counter, secure hash } sm_key_t csrk; - central_device_db_csrk(att_ir_central_device_db_index, csrk); + central_device_db_csrk_get(att_ir_central_device_db_index, csrk); att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION; log_info("Orig Signature: "); hexdump( &att_request_buffer[att_request_size-8], 8); diff --git a/ble/central_device_db.h b/ble/central_device_db.h index 8b7a57bbb..621deca4c 100644 --- a/ble/central_device_db.h +++ b/ble/central_device_db.h @@ -69,10 +69,10 @@ void central_device_db_init(); /** * @brief add device to db * @param addr_type, address of the device - * @param irk and csrk of the device + * @param irk of the device * @returns index if successful, -1 otherwise */ -int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t csrk); +int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk); /** * @brief get number of devices in db for enumeration @@ -88,26 +88,66 @@ int central_device_db_count(void); */ void central_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk); + +/** + * @brief set remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk); + +/** + * @brief get remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk); + +/** + * @brief set signing key for this device + * @param index + * @param signing key as input + */ +void central_device_db_csrk_set(int index, sm_key_t csrk); + /** * @brief get signing key for this device * @param index * @param signing key as output */ -void central_device_db_csrk(int index, sm_key_t csrk); +void central_device_db_csrk_get(int index, sm_key_t csrk); /** * @brief query last used/seen signing counter * @param index * @returns next expected counter, 0 after devices was added */ -uint32_t central_device_db_counter_get(int index); +uint32_t central_device_db_remote_counter_get(int index); /** * @brief update signing counter * @param index * @param counter to store */ -void central_device_db_counter_set(int index, uint32_t counter); +void central_device_db_remote_counter_set(int index, uint32_t counter); + +/** + * @brief query last used/seen signing counter + * @param index + * @returns next expected counter, 0 after devices was added + */ +uint32_t central_device_db_local_counter_get(int index); + +/** + * @brief update signing counter + * @param index + * @param counter to store + */ +void central_device_db_local_counter_set(int index, uint32_t counter); /** * @brief free device diff --git a/ble/central_device_db_dummy.c b/ble/central_device_db_dummy.c index ae1dcbe59..6af63bb14 100644 --- a/ble/central_device_db_dummy.c +++ b/ble/central_device_db_dummy.c @@ -40,7 +40,7 @@ void central_device_db_init(){} // @returns index if successful, -1 otherwise -int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t csrk){ +int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){ return -1; } @@ -49,19 +49,45 @@ int central_device_db_count(void){ return 0; } +/** + * @brief set remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk){} + +/** + * @brief get remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk){} + // get device information: addr type and address void central_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t csrk){} // get signature key -void central_device_db_csrk(int index, sm_key_t csrk){} +void central_device_db_csrk_get(int index, sm_key_t csrk){} // query last used/seen signing counter -uint32_t central_device_db_counter_get(int index){ +uint32_t central_device_db_remote_counter_get(int index){ return 0xffffffff; } // update signing counter -void central_device_db_counter_set(int index, uint32_t counter){} +void central_device_db_local_counter_set(int index, uint32_t counter){} + +// query last used/seen signing counter +uint32_t central_device_db_local_counter_get(int index){ + return 0xffffffff; +} + +// update signing counter +void central_device_db_remote_counter_set(int index, uint32_t counter){} // free device void central_device_db_remove(int index){} diff --git a/ble/central_device_db_memory.c b/ble/central_device_db_memory.c index a8904e4be..d4e756adf 100644 --- a/ble/central_device_db_memory.c +++ b/ble/central_device_db_memory.c @@ -86,12 +86,12 @@ int central_device_db_count(void){ return counter; } -// free device - TODO not implemented +// free device void central_device_db_remove(int index){ central_devices[index].addr_type = INVALID_ENTRY_ADDR_TYPE; } -int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t csrk){ +int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){ int i; int index = -1; for (i=0;i<CENTRAL_DEVICE_MEMORY_SIZE;i++){ @@ -105,11 +105,9 @@ int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t log_info("Central Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr)); log_key("irk", irk); - log_key("csrk", csrk); central_devices[index].addr_type = addr_type; memcpy(central_devices[index].addr, addr, 6); - memcpy(central_devices[index].csrk, csrk, 16); memcpy(central_devices[index].irk, irk, 16); central_devices[index].remote_counter = 0; @@ -124,22 +122,61 @@ void central_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t if (irk) memcpy(irk, central_devices[index].irk, 16); } +/** + * @brief set remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk){ + central_devices[index].ediv = ediv; + if (rand) memcpy(central_devices[index].rand, rand, 8); + if (ltk) memcpy(central_devices[index].ltk, ltk, 16); +} + +/** + * @brief get remote encryption info + * @brief index + * @brief ediv + * @brief rand + * @brief ltk + */ +void central_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk){ + if (ediv) *ediv = central_devices[index].ediv; + if (rand) memcpy(rand, central_devices[index].rand, 8); + if (ltk) memcpy(ltk, central_devices[index].ltk, 16); +} + // get signature key -void central_device_db_csrk(int index, sm_key_t csrk){ +void central_device_db_csrk_get(int index, sm_key_t csrk){ if (csrk) memcpy(csrk, central_devices[index].csrk, 16); } +void central_device_db_csrk_set(int index, sm_key_t csrk){ + if (csrk) memcpy(central_devices[index].csrk, csrk, 16); +} // query last used/seen signing counter -uint32_t central_device_db_counter_get(int index){ +uint32_t central_device_db_remote_counter_get(int index){ return central_devices[index].remote_counter; } // update signing counter -void central_device_db_counter_set(int index, uint32_t counter){ +void central_device_db_remote_counter_set(int index, uint32_t counter){ central_devices[index].remote_counter = counter; } +// query last used/seen signing counter +uint32_t central_device_db_local_counter_get(int index){ + return central_devices[index].local_counter; +} + +// update signing counter +void central_device_db_local_counter_set(int index, uint32_t counter){ + central_devices[index].local_counter = counter; +} + void central_device_db_dump(){ log_info("Central Device DB dump, devices: %u", central_device_db_count); int i; diff --git a/ble/sm.c b/ble/sm.c index 563a0ab19..1fe807632 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -215,8 +215,10 @@ typedef struct sm_setup_context { uint8_t sm_peer_rand[8]; sm_key_t sm_peer_ltk; sm_key_t sm_peer_irk; + sm_key_t sm_peer_csrk; uint8_t sm_peer_addr_type; bd_addr_t sm_peer_address; + } sm_setup_context_t; // @@ -1579,6 +1581,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint sm_conn->sm_connection_encrypted = 0; sm_conn->sm_connection_authenticated = 0; sm_conn->sm_connection_authorization_state = AUTHORIZATION_UNKNOWN; + sm_conn->sm_central_db_index = -1; // prepare CSRK lookup (does not involve setup) sm_conn->sm_csrk_lookup_state = CSRK_LOOKUP_W4_READY; @@ -1733,7 +1736,6 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac log_debug("sm_packet_handler: state %u, pdu 0x%02x", sm_conn->sm_engine_state, packet[0]); - sm_key_t csrk; int err; switch (sm_conn->sm_engine_state){ @@ -1869,13 +1871,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac case SM_CODE_SIGNING_INFORMATION: setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; - swap128(&packet[1], csrk); - - // store, if: it's a public address, or, we got an IRK - if (setup->sm_peer_addr_type == 0 || (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION)) { - sm_central_device_matched = central_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk, csrk); - break; - } + swap128(&packet[1], setup->sm_peer_csrk); break; default: // Unexpected PDU @@ -1884,6 +1880,29 @@ 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()){ + + // store, if: it's a public address, or, we got an IRK + if (setup->sm_peer_addr_type == 0 || (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION)) { + sm_conn->sm_central_db_index = central_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk); + } + + if (sm_conn->sm_central_db_index >= 0){ + central_device_db_local_counter_set(sm_conn->sm_central_db_index, 0); + + // store CSRK + if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ + central_device_db_csrk_set(sm_conn->sm_central_db_index, setup->sm_peer_csrk); + central_device_db_remote_counter_set(sm_conn->sm_central_db_index, 0); + } + + // store encryption information as Central + if (sm_conn->sm_role == 0 + && setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION + && setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION){ + central_device_db_encryption_set(sm_conn->sm_central_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk); + } + } + if (sm_conn->sm_role){ sm_conn->sm_engine_state = SM_GENERAL_IDLE; sm_done_for_handle(sm_conn->sm_handle);