mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-27 06:35:20 +00:00
store all received keys (aside from peer addr and type)
This commit is contained in:
parent
e14eb8abef
commit
cb7e8bd038
105
ble/sm.c
105
ble/sm.c
@ -290,36 +290,37 @@ typedef struct sm_setup_context {
|
||||
sm_key_t sm_local_random;
|
||||
sm_key_t sm_local_confirm;
|
||||
|
||||
// key distribution, we generate
|
||||
uint16_t sm_local_y;
|
||||
uint16_t sm_local_div;
|
||||
uint16_t sm_local_ediv;
|
||||
uint8_t sm_local_rand[8];
|
||||
sm_key_t sm_local_ltk;
|
||||
sm_key_t sm_local_csrk;
|
||||
sm_key_t sm_local_irk;
|
||||
|
||||
// peer
|
||||
sm_key_t sm_peer_random;
|
||||
sm_key_t sm_peer_confirm;
|
||||
|
||||
// key distribution, received from peer
|
||||
uint16_t sm_peer_y;
|
||||
uint16_t sm_peer_div;
|
||||
uint16_t sm_peer_ediv;
|
||||
uint8_t sm_peer_rand[8];
|
||||
sm_key_t sm_peer_ltk;
|
||||
sm_key_t sm_peer_csrk;
|
||||
sm_key_t sm_peer_irk;
|
||||
|
||||
// master
|
||||
sm_pairing_packet_t sm_m_preq; // pairing request
|
||||
|
||||
// key distribution, received from master
|
||||
// commented keys that are not stored or used by Peripheral role
|
||||
// uint16_t sm_m_y;
|
||||
// uint16_t sm_m_div;
|
||||
// uint16_t sm_m_ediv;
|
||||
// uint8_t sm_m_rand[8];
|
||||
uint8_t sm_m_addr_type;
|
||||
bd_addr_t sm_m_address;
|
||||
sm_key_t sm_m_csrk;
|
||||
sm_key_t sm_m_irk;
|
||||
|
||||
// slave
|
||||
sm_pairing_packet_t sm_s_pres; // pairing response
|
||||
|
||||
// key distribution, slave sends
|
||||
uint16_t sm_s_y;
|
||||
uint16_t sm_s_div;
|
||||
uint16_t sm_s_ediv;
|
||||
uint8_t sm_s_rand[8];
|
||||
// commented keys are not used in Perihperal role
|
||||
uint8_t sm_s_addr_type;
|
||||
bd_addr_t sm_s_address;
|
||||
// sm_key_t sm_s_csrk;
|
||||
|
||||
} sm_setup_context_t;
|
||||
|
||||
@ -647,7 +648,7 @@ static void sm_central_device_start_lookup(uint8_t addr_type, bd_addr_t addr){
|
||||
|
||||
// TODO use relevant connection structure
|
||||
static void sm_central_device_lookup_found(sm_key_t csrk){
|
||||
memcpy(setup->sm_m_csrk, csrk, 16);
|
||||
memcpy(setup->sm_peer_csrk, csrk, 16);
|
||||
}
|
||||
|
||||
// CMAC Implementation using AES128 engine
|
||||
@ -1091,7 +1092,7 @@ static void sm_run(void){
|
||||
if (sm_aes128_state == SM_AES128_ACTIVE) break;
|
||||
// PH3B2 - calculate Y from - enc
|
||||
// Y = dm(DHK, Rand)
|
||||
sm_dm_r_prime(setup->sm_s_rand, plaintext);
|
||||
sm_dm_r_prime(setup->sm_local_rand, plaintext);
|
||||
sm_aes128_start(sm_persistent_dhk, plaintext);
|
||||
sm_next_responding_state();
|
||||
return;
|
||||
@ -1132,9 +1133,9 @@ static void sm_run(void){
|
||||
case SM_STATE_PH4_Y_GET_ENC:
|
||||
// already busy?
|
||||
if (sm_aes128_state == SM_AES128_ACTIVE) break;
|
||||
log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_s_ediv);
|
||||
log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_local_ediv);
|
||||
// Y = dm(DHK, Rand)
|
||||
sm_dm_r_prime(setup->sm_s_rand, plaintext);
|
||||
sm_dm_r_prime(setup->sm_local_rand, plaintext);
|
||||
sm_aes128_start(sm_persistent_dhk, plaintext);
|
||||
sm_next_responding_state();
|
||||
return;
|
||||
@ -1153,8 +1154,8 @@ static void sm_run(void){
|
||||
setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
|
||||
uint8_t buffer[11];
|
||||
buffer[0] = SM_CODE_MASTER_IDENTIFICATION;
|
||||
bt_store_16(buffer, 1, setup->sm_s_ediv);
|
||||
swap64(setup->sm_s_rand, &buffer[3]);
|
||||
bt_store_16(buffer, 1, setup->sm_local_ediv);
|
||||
swap64(setup->sm_local_rand, &buffer[3]);
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||
sm_2timeout_reset();
|
||||
return;
|
||||
@ -1182,7 +1183,7 @@ static void sm_run(void){
|
||||
setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_SIGNING_INFORMATION;
|
||||
// swap128(sm_s_csrk, &buffer[1]);
|
||||
// swap128(sm_local_csrk, &buffer[1]);
|
||||
memset(&buffer[1], 0, 16); // csrk not calculated
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||
sm_2timeout_reset();
|
||||
@ -1321,28 +1322,28 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
case SM_STATE_PH3_Y_W4_ENC:{
|
||||
sm_key_t y128;
|
||||
swap128(data, y128);
|
||||
setup->sm_s_y = READ_NET_16(y128, 14);
|
||||
print_hex16("y", setup->sm_s_y);
|
||||
setup->sm_local_y = READ_NET_16(y128, 14);
|
||||
print_hex16("y", setup->sm_local_y);
|
||||
// PH3B3 - calculate EDIV
|
||||
setup->sm_s_ediv = setup->sm_s_y ^ setup->sm_s_div;
|
||||
print_hex16("ediv", setup->sm_s_ediv);
|
||||
setup->sm_local_ediv = setup->sm_local_y ^ setup->sm_local_div;
|
||||
print_hex16("ediv", setup->sm_local_ediv);
|
||||
// PH3B4 - calculate LTK - enc
|
||||
// LTK = d1(ER, DIV, 0))
|
||||
sm_d1_d_prime(setup->sm_s_div, 0, setup->sm_aes128_plaintext);
|
||||
sm_d1_d_prime(setup->sm_local_div, 0, setup->sm_aes128_plaintext);
|
||||
connection->sm_state_responding = SM_STATE_PH3_LTK_GET_ENC;
|
||||
return;
|
||||
}
|
||||
case SM_STATE_PH4_Y_W4_ENC:{
|
||||
sm_key_t y128;
|
||||
swap128(data, y128);
|
||||
setup->sm_s_y = READ_NET_16(y128, 14);
|
||||
print_hex16("y", setup->sm_s_y);
|
||||
setup->sm_local_y = READ_NET_16(y128, 14);
|
||||
print_hex16("y", setup->sm_local_y);
|
||||
// PH3B3 - calculate DIV
|
||||
setup->sm_s_div = setup->sm_s_y ^ setup->sm_s_ediv;
|
||||
print_hex16("ediv", setup->sm_s_ediv);
|
||||
setup->sm_local_div = setup->sm_local_y ^ setup->sm_local_ediv;
|
||||
print_hex16("ediv", setup->sm_local_ediv);
|
||||
// PH3B4 - calculate LTK - enc
|
||||
// LTK = d1(ER, DIV, 0))
|
||||
sm_d1_d_prime(setup->sm_s_div, 0, setup->sm_aes128_plaintext);
|
||||
sm_d1_d_prime(setup->sm_local_div, 0, setup->sm_aes128_plaintext);
|
||||
connection->sm_state_responding = SM_STATE_PH4_LTK_GET_ENC;
|
||||
return;
|
||||
}
|
||||
@ -1418,17 +1419,17 @@ static void sm_handle_random_result(uint8_t * data){
|
||||
connection->sm_state_responding = SM_STATE_PH2_C1_GET_ENC_A;
|
||||
return;
|
||||
case SM_STATE_PH3_W4_RANDOM:
|
||||
swap64(data, setup->sm_s_rand);
|
||||
// no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_s_rand
|
||||
setup->sm_s_rand[7] = (setup->sm_s_rand[7] & 0xf0) + (connection->sm_actual_encryption_key_size - 1);
|
||||
swap64(data, setup->sm_local_rand);
|
||||
// no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
|
||||
setup->sm_local_rand[7] = (setup->sm_local_rand[7] & 0xf0) + (connection->sm_actual_encryption_key_size - 1);
|
||||
// no db for authenticated flag hack: store flag in bit 4 of LSB
|
||||
setup->sm_s_rand[7] = (setup->sm_s_rand[7] & 0xef) + (connection->sm_connection_authenticated << 4);
|
||||
setup->sm_local_rand[7] = (setup->sm_local_rand[7] & 0xef) + (connection->sm_connection_authenticated << 4);
|
||||
connection->sm_state_responding = SM_STATE_PH3_GET_DIV;
|
||||
return;
|
||||
case SM_STATE_PH3_W4_DIV:
|
||||
// use 16 bit from random value as div
|
||||
setup->sm_s_div = READ_NET_16(data, 0);
|
||||
print_hex16("div", setup->sm_s_div);
|
||||
setup->sm_local_div = READ_NET_16(data, 0);
|
||||
print_hex16("div", setup->sm_local_div);
|
||||
connection->sm_state_responding = SM_STATE_PH3_Y_GET_ENC;
|
||||
return;
|
||||
default:
|
||||
@ -1545,22 +1546,22 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
}
|
||||
|
||||
// re-establish previously used LTK using Rand and EDIV
|
||||
swap64(&packet[5], setup->sm_s_rand);
|
||||
setup->sm_s_ediv = READ_BT_16(packet, 13);
|
||||
swap64(&packet[5], setup->sm_local_rand);
|
||||
setup->sm_local_ediv = READ_BT_16(packet, 13);
|
||||
|
||||
// assume that we don't have a LTK for ediv == 0 and random == null
|
||||
if (setup->sm_s_ediv == 0 && sm_is_null_random(setup->sm_s_rand)){
|
||||
if (setup->sm_local_ediv == 0 && sm_is_null_random(setup->sm_local_rand)){
|
||||
printf("LTK Request: ediv & random are empty\n");
|
||||
connection->sm_state_responding = SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
|
||||
break;
|
||||
}
|
||||
|
||||
// re-establish used key encryption size
|
||||
// no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_s_rand
|
||||
connection->sm_actual_encryption_key_size = (setup->sm_s_rand[7] & 0x0f) + 1;
|
||||
// no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
|
||||
connection->sm_actual_encryption_key_size = (setup->sm_local_rand[7] & 0x0f) + 1;
|
||||
|
||||
// no db for authenticated flag hack: flag is stored in bit 4 of LSB
|
||||
connection->sm_connection_authenticated = (setup->sm_s_rand[7] & 0x10) >> 4;
|
||||
connection->sm_connection_authenticated = (setup->sm_local_rand[7] & 0x10) >> 4;
|
||||
|
||||
connection->sm_state_responding = SM_STATE_PH4_Y_GET_ENC;
|
||||
break;
|
||||
@ -1824,18 +1825,18 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
||||
switch(packet[0]){
|
||||
case SM_CODE_ENCRYPTION_INFORMATION:
|
||||
setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
|
||||
// swap128(&packet[1], sm_m_ltk);
|
||||
swap128(&packet[1], setup->sm_peer_ltk);
|
||||
break;
|
||||
|
||||
case SM_CODE_MASTER_IDENTIFICATION:
|
||||
setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
|
||||
// sm_m_ediv = READ_BT_16(packet, 1);
|
||||
// swap64(&packet[3], sm_m_rand);
|
||||
setup->sm_peer_ediv = READ_BT_16(packet, 1);
|
||||
swap64(&packet[3], setup->sm_peer_rand);
|
||||
break;
|
||||
|
||||
case SM_CODE_IDENTITY_INFORMATION:
|
||||
setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
|
||||
swap128(&packet[1], setup->sm_m_irk);
|
||||
swap128(&packet[1], setup->sm_peer_irk);
|
||||
break;
|
||||
|
||||
case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
|
||||
@ -1848,11 +1849,11 @@ 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], setup->sm_m_csrk);
|
||||
swap128(&packet[1], setup->sm_peer_csrk);
|
||||
|
||||
// store, if: it's a public address, or, we got an IRK
|
||||
if (setup->sm_m_addr_type == 0 || (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION)) {
|
||||
sm_central_device_matched = central_device_db_add(setup->sm_m_addr_type, setup->sm_m_address, setup->sm_m_irk, setup->sm_m_csrk);
|
||||
sm_central_device_matched = central_device_db_add(setup->sm_m_addr_type, setup->sm_m_address, setup->sm_peer_irk, setup->sm_peer_csrk);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user