Skip to content
Permalink
Browse files

le_device_db: add secure connection field

  • Loading branch information...
mringwal committed Mar 6, 2019
1 parent a9987c8 commit 3dc3a67de7561c8a54a65eb5452fd671398da3c8
@@ -61,6 +61,7 @@ typedef struct le_device_memory_db {
uint8_t key_size;
uint8_t authenticated;
uint8_t authorized;
uint8_t secure_connection;

#ifdef ENABLE_LE_SIGNED_WRITE
// Signed Writes by remote
@@ -87,7 +88,12 @@ typedef struct le_device_memory_db {

#define DB_PATH_TEMPLATE (LE_DEVICE_DB_PATH "btstack_at_%s_le_device_db.txt")

const char * csv_header = "# addr_type, addr, irk, ltk, ediv, rand[8], key_size, authenticated, authorized, remote_csrk, remote_counter, local_csrk, local_counter";
#ifdef ENABLE_LE_SIGNED_WRITE
const char * csv_header = "# addr_type, addr, irk, ltk, ediv, rand[8], key_size, authenticated, authorized, remote_csrk, remote_counter, local_csrk, local_counter, secure_connection";
#else
const char * csv_header = "# addr_type, addr, irk, ltk, ediv, rand[8], key_size, authenticated, authorized, secure_connection";
#endif

static char db_path[sizeof(DB_PATH_TEMPLATE) - 2 + 17 + 1];

static le_device_memory_db_t le_devices[LE_DEVICE_MEMORY_SIZE];
@@ -165,6 +171,7 @@ static void le_device_db_store(void) {
write_hex(wFile, le_devices[i].local_csrk, 16);
write_value(wFile, le_devices[i].local_counter, 2);
#endif
write_value(wFile, le_devices[i].secure_connection, 1);
fwrite("\n", 1, 1, wFile);
}
fclose(wFile);
@@ -213,6 +220,7 @@ static void le_device_db_read(void){
// read entries
int i;
for (i=0 ; i<LE_DEVICE_MEMORY_SIZE ; i++){
memset(&le_devices[i], 0, sizeof(le_device_memory_db_t));
le_devices[i].addr_type = read_value(wFile, 1);
if (feof(wFile)){
le_devices[i].addr_type = INVALID_ENTRY_ADDR_TYPE;
@@ -232,8 +240,14 @@ static void le_device_db_read(void){
read_hex(wFile, le_devices[i].local_csrk, 16);
le_devices[i].local_counter = read_value(wFile, 2);
#endif
// read newling
fgetc(wFile);
// read next character and secure connection field if hex nibble follows
int c = fgetc(wFile);
if (nibble_for_char(c) >= 0){
int d = fgetc(wFile);
le_devices[i].secure_connection = nibble_for_char(c) << 4 | nibble_for_char(d);
// read newline
fgetc(wFile);
}
}
exit:
fclose(wFile);
@@ -310,30 +324,32 @@ void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk)
if (irk) memcpy(irk, le_devices[index].irk, 16);
}

void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized){
log_info("Central Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
index, ediv, key_size, authenticated, authorized);
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
index, ediv, key_size, authenticated, authorized, secure_connection);
le_device_memory_db_t * device = &le_devices[index];
device->ediv = ediv;
if (rand) memcpy(device->rand, rand, 8);
if (ltk) memcpy(device->ltk, ltk, 16);
device->key_size = key_size;
device->authenticated = authenticated;
device->authorized = authorized;
device->secure_connection = secure_connection;

le_device_db_store();
}

void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized){
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){
le_device_memory_db_t * device = &le_devices[index];
log_info("Central Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
index, device->ediv, device->key_size, device->authenticated, device->authorized);
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
index, device->ediv, device->key_size, device->authenticated, device->authorized, device->secure_connection);
if (ediv) *ediv = device->ediv;
if (rand) memcpy(rand, device->rand, 8);
if (ltk) memcpy(ltk, device->ltk, 16);
if (key_size) *key_size = device->key_size;
if (authenticated) *authenticated = device->authenticated;
if (authorized) *authorized = device->authorized;
if (secure_connection) *secure_connection = device->secure_connection;
}

#ifdef ENABLE_LE_SIGNED_WRITE
@@ -73,6 +73,8 @@ typedef struct le_device_nvm {
uint8_t key_size;
uint8_t authenticated;
uint8_t authorized;
uint8_t secure_connection;

sm_key_t ltk;

// Stored pairing information allows to re-establish an enncrypted connection
@@ -243,40 +245,42 @@ int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
return absolute_index;
}

void le_device_db_encryption_set(int device_index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized){
void le_device_db_encryption_set(int device_index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){

int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
le_device_nvm_t entry;
le_device_db_entry_read(absolute_index, &entry);

log_info("set encryption for #%u, ediv 0x%04x, key size %u, authenticated %u, authorized %u",
absolute_index, ediv, key_size, authenticated, authorized);
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
device_index, ediv, key_size, authenticated, authorized, secure_connection);

entry.ediv = ediv;
if (rand) memcpy(entry.rand, rand, 8);
if (ltk) memcpy(entry.ltk, ltk, 16);
entry.key_size = key_size;
entry.authenticated = authenticated;
entry.authorized = authorized;
entry.secure_connection = secure_connection;

le_device_db_entry_write(absolute_index, &entry);
}

void le_device_db_encryption_get(int device_index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized){
void le_device_db_encryption_get(int device_index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){

int absolute_index = le_device_db_get_absolute_index_for_device_index(device_index);
le_device_nvm_t entry;
le_device_db_entry_read(absolute_index, &entry);

log_info("encryption for #%u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
absolute_index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
device_index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized, entry.secure_connection);

if (ediv) *ediv = entry.ediv;
if (rand) memcpy(rand, entry.rand, 8);
if (ltk) memcpy(ltk, entry.ltk, 16);
if (key_size) *key_size = entry.key_size;
if (authenticated) *authenticated = entry.authenticated;
if (authorized) *authorized = entry.authorized;
if (secure_connection) *secure_connection = entry.secure_connection;
}

void le_device_db_dump(void){
@@ -113,8 +113,9 @@ void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk)
* @brief key size
* @brief authenticated
* @brief authorized
* @breif secure_connection
*/
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized);
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection);

/**
* @brief get remote encryption info
@@ -125,8 +126,9 @@ void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_k
* @brief key size
* @brief authenticated
* @brief authorized
* @breif secure_connection
*/
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized);
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection);

#ifdef ENABLE_LE_SIGNED_WRITE

@@ -63,6 +63,7 @@ typedef struct le_device_memory_db {
uint8_t key_size;
uint8_t authenticated;
uint8_t authorized;
uint8_t secure_connection;

#ifdef ENABLE_LE_SIGNED_WRITE
// Signed Writes by remote
@@ -146,28 +147,30 @@ void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk)
if (irk) memcpy(irk, le_devices[index].irk, 16);
}

void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized){
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
index, ediv, key_size, authenticated, authorized);
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
index, ediv, key_size, authenticated, authorized, secure_connection);
le_device_memory_db_t * device = &le_devices[index];
device->ediv = ediv;
if (rand) memcpy(device->rand, rand, 8);
if (ltk) memcpy(device->ltk, ltk, 16);
device->key_size = key_size;
device->authenticated = authenticated;
device->authorized = authorized;
device->secure_connection = secure_connection;
}

void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized){
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){
le_device_memory_db_t * device = &le_devices[index];
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
index, device->ediv, device->key_size, device->authenticated, device->authorized);
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized, entry.secure_connection);
if (ediv) *ediv = device->ediv;
if (rand) memcpy(rand, device->rand, 8);
if (ltk) memcpy(ltk, device->ltk, 16);
if (key_size) *key_size = device->key_size;
if (authenticated) *authenticated = device->authenticated;
if (authorized) *authorized = device->authorized;
if (secure_connection) *secure_connection = device->secure_connection;
}

#ifdef ENABLE_LE_SIGNED_WRITE
@@ -66,9 +66,11 @@ typedef struct le_device_db_entry_t {
sm_key_t ltk;
uint16_t ediv;
uint8_t rand[8];

uint8_t key_size;
uint8_t authenticated;
uint8_t authorized;
uint8_t secure_connection;

#ifdef ENABLE_LE_SIGNED_WRITE
// Signed Writes by remote
@@ -290,43 +292,45 @@ void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk)
if (irk) memcpy(irk, entry.irk, 16);
}

void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized){
void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){

// fetch entry
le_device_db_entry_t entry;
int ok = le_device_db_tlv_fetch(index, &entry);
if (!ok) return;

// update
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
index, ediv, key_size, authenticated, authorized);
log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
index, ediv, key_size, authenticated, authorized, secure_connection);
entry.ediv = ediv;
if (rand) memcpy(entry.rand, rand, 8);
if (ltk) memcpy(entry.ltk, ltk, 16);
entry.key_size = key_size;
entry.authenticated = authenticated;
entry.authorized = authorized;
entry.secure_connection = secure_connection;

// store
le_device_db_tlv_store(index, &entry);
}

void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized){
void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){

// fetch entry
le_device_db_entry_t entry;
int ok = le_device_db_tlv_fetch(index, &entry);
if (!ok) return;

// update user fields
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized, entry.secure_connection);
if (ediv) *ediv = entry.ediv;
if (rand) memcpy(rand, entry.rand, 8);
if (ltk) memcpy(ltk, entry.ltk, 16);
if (key_size) *key_size = entry.key_size;
if (authenticated) *authenticated = entry.authenticated;
if (authorized) *authorized = entry.authorized;
if (secure_connection) *secure_connection = entry.secure_connection;
}

#ifdef ENABLE_LE_SIGNED_WRITE
@@ -1175,7 +1175,7 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
break;
}
#ifdef ENABLE_LE_CENTRAL
le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL);
le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
have_ltk = !sm_is_null_key(ltk);
pairing_need = sm_connection->sm_pairing_requested || sm_connection->sm_security_request_received;
log_info("central: pairing request local %u, remote %u => action %u. have_ltk %u",
@@ -1317,15 +1317,15 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
uint8_t zero_rand[8];
memset(zero_rand, 0, 8);
le_device_db_encryption_set(le_db_index, 0, zero_rand, setup->sm_ltk, sm_conn->sm_actual_encryption_key_size,
sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED);
sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 1);
}

// store encryption information for legacy pairing: peer LTK, EDIV, RAND
else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
&& (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION )){
log_info("sm: set encryption information (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED);
sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 0);

}
}
@@ -1781,14 +1781,16 @@ static void sm_load_security_info(sm_connection_t * sm_connection){
int encryption_key_size;
int authenticated;
int authorized;
int secure_connection;

// fetch data from device db - incl. authenticated/authorized/key size. Note all sm_connection_X require encryption enabled
le_device_db_encryption_get(sm_connection->sm_le_db_index, &setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
&encryption_key_size, &authenticated, &authorized);
log_info("db index %u, key size %u, authenticated %u, authorized %u", sm_connection->sm_le_db_index, encryption_key_size, authenticated, authorized);
&encryption_key_size, &authenticated, &authorized, &secure_connection);
log_info("db index %u, key size %u, authenticated %u, authorized %u, secure connetion %u", sm_connection->sm_le_db_index, encryption_key_size, authenticated, authorized, secure_connection);
sm_connection->sm_actual_encryption_key_size = encryption_key_size;
sm_connection->sm_connection_authenticated = authenticated;
sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
sm_connection->sm_connection_sc = secure_connection;
}
#endif

@@ -1801,6 +1803,8 @@ static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_con
sm_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
sm_connection->sm_connection_authenticated = (setup->sm_local_rand[7] & 0x10) >> 4;
// Legacy paring -> not SC
sm_connection->sm_connection_sc = 0;
log_info("sm: received ltk request with key size %u, authenticated %u",
sm_connection->sm_actual_encryption_key_size, sm_connection->sm_connection_authenticated);
sm_connection->sm_engine_state = SM_RESPONDER_PH4_Y_GET_ENC;
@@ -3966,7 +3970,7 @@ void sm_request_pairing(hci_con_handle_t con_handle){
switch (sm_conn->sm_irk_lookup_state){
case IRK_LOOKUP_SUCCEEDED:
#ifndef ENABLE_LE_CENTRAL_AUTO_ENCRYPTION
le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL);
le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
int have_ltk = !sm_is_null_key(ltk);
log_info("have ltk %u", have_ltk);
// trigger 'pairing complete' event on encryption change
@@ -388,6 +388,7 @@ typedef struct sm_connection {
irk_lookup_state_t sm_irk_lookup_state;
uint8_t sm_connection_encrypted;
uint8_t sm_connection_authenticated; // [0..1]
uint8_t sm_connection_sc;
uint8_t sm_actual_encryption_key_size;
sm_pairing_packet_t sm_m_preq; // only used during c1
authorization_state_t sm_connection_authorization_state;

0 comments on commit 3dc3a67

Please sign in to comment.
You can’t perform that action at this time.