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;ism_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);