sm: generate and store ER / IR keys in TLV, unless manually set by application

This commit is contained in:
Matthias Ringwald 2018-12-04 10:20:20 +01:00
parent 5b4dd59758
commit 899e6e028a
3 changed files with 109 additions and 14 deletions

View File

@ -11,9 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Nordic SPP Service Server: GATT service that emulates a serial port over BLE based on Nordic Semiconductor documentation.
- uBlox SPP Service Server: GATT service that emulates a serial port over BLE based on uBlox documentation.
- SM: ENABLE_LE_CENTRAL_AUTO_ENCRYPTION triggers automatic encryption on connect to bonded devices
- SM: generate and store ER / IR keys in TLV, unless manually set by application
### Fixed
- SM: prevent random address updates if gap_random_address_set was used
- SM: fix internal buffer overrun during random address generation
- SM: fix internal buffer overrun that can cause storing of bonding information to fail
- SM: ignore Slave Security Request after sending own Pairing Request
- L2CAP: fix use after free on disconnect if ERTM is enabled

View File

@ -49,6 +49,7 @@
#include "btstack_event.h"
#include "btstack_linked_list.h"
#include "btstack_memory.h"
#include "btstack_tlv.h"
#include "gap.h"
#include "hci.h"
#include "hci_dump.h"
@ -81,6 +82,8 @@
#define USE_CMAC_ENGINE
#endif
#define BTSTACK_TAG32(A,B,C,D) ((A << 24) | (B << 16) | (C << 8) | D)
//
// SM internal types and globals
//
@ -193,6 +196,11 @@ static void (*sm_sc_oob_callback)(const uint8_t * confirm_value, const uint8_t *
static sm_sc_oob_state_t sm_sc_oob_state;
#endif
static uint8_t sm_persistent_keys_random_active;
static const btstack_tlv_t * sm_tlv_impl;
static void * sm_tlv_context;
// Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values
static sm_key_t sm_persistent_er;
static sm_key_t sm_persistent_ir;
@ -499,6 +507,31 @@ static void sm_truncate_key(sm_key_t key, int max_encryption_size){
}
}
// ER / IR checks
static int sm_er_ir_set_default(void){
int i;
for (i=0;i<16;i++){
sm_persistent_er[i] = 0x30 + i;
sm_persistent_ir[i] = 0x90 + i;
}
}
static int sm_er_is_default(void){
int i;
for (i=0;i<16;i++){
if (sm_persistent_er[i] != (0x30+i)) return 0;
}
return 1;
}
static int sm_ir_is_default(void){
int i;
for (i=0;i<16;i++){
if (sm_persistent_ir[i] != (0x90+i)) return 0;
}
return 1;
}
// SMP Timeout implementation
// Upon transmission of the Pairing Request command or reception of the Pairing Request command,
@ -544,7 +577,7 @@ static btstack_timer_source_t gap_random_address_update_timer;
static uint32_t gap_random_adress_update_period;
static void gap_random_address_trigger(void){
log_info("gap_random_address_trigger");
log_info("gap_random_address_trigger, state %u", rau_state);
if (rau_state != RAU_IDLE) return;
rau_state = RAU_GET_RANDOM;
sm_run();
@ -1783,6 +1816,9 @@ static void sm_run(void){
// assert that we can send at least commands
if (!hci_can_send_command_packet_now()) return;
// pause until IR/ER are ready
if (sm_persistent_keys_random_active) return;
//
// non-connection related behaviour
//
@ -2766,7 +2802,6 @@ static void sm_handle_encryption_result_dkg_dhk(void *arg){
sm_aes128_state = SM_AES128_IDLE;
log_info_key("dhk", sm_persistent_dhk);
dkg_state = DKG_READY;
// DKG calculation complete => SM Init Finished
sm_run();
}
@ -2877,6 +2912,52 @@ static void sm_handle_random_result_ph3_random(void * arg){
setup->sm_local_rand[7] = (setup->sm_local_rand[7] & 0xef) + (connection->sm_connection_authenticated << 4);
btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 2, &sm_handle_random_result_ph3_div, connection);
}
static void sm_validate_er_ir(void){
// warn about default ER/IR
int warning = 0;
if (sm_ir_is_default()){
warning = 1;
log_error("Persistent IR not set with sm_set_ir. Use of private addresses will cause pairing issues");
}
if (sm_er_is_default()){
warning = 1;
log_error("Persistent ER not set with sm_set_er. Legacy Pairing LTK is not secure");
}
log_error("Please configure btstack_tlv to let BTstack setup ER and IR keys");
}
static void sm_handle_random_result_ir(void *arg){
sm_persistent_keys_random_active = 0;
if (arg){
// key generated, store in tlv
int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16);
log_info("Generated IR key. Store in TLV status: %d", status);
}
log_info_key("IR", sm_persistent_ir);
sm_run();
}
static void sm_handle_random_result_er(void *arg){
sm_persistent_keys_random_active = 0;
if (arg){
// key generated, store in tlv
int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16);
log_info("Generated ER key. Store in TLV status: %d", status);
}
log_info_key("ER", sm_persistent_er);
// try load ir
int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16);
if (key_size == 16){
// ok, let's continue
log_info("IR from TLV");
sm_handle_random_result_ir( NULL );
} else {
// invalid, generate new random one
sm_persistent_keys_random_active = 1;
btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_ir, 16, &sm_handle_random_result_ir, &sm_persistent_ir);
}
}
static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
@ -2895,6 +2976,23 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// bt stack activated, get started
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
log_info("HCI Working!");
// setup IR/ER with TLV
btstack_tlv_get_instance(&sm_tlv_impl, &sm_tlv_context);
if (sm_tlv_impl){
int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16);
if (key_size == 16){
// ok, let's continue
log_info("ER from TLV");
sm_handle_random_result_er( NULL );
} else {
// invalid, generate random one
sm_persistent_keys_random_active = 1;
btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_er, 16, &sm_handle_random_result_er, &sm_persistent_er);
}
} else {
sm_validate_er_ir();
}
}
break;
@ -3753,16 +3851,9 @@ void sm_test_set_pairing_failure(int reason){
#endif
void sm_init(void){
// set some (BTstack default) ER and IR
int i;
sm_key_t er;
sm_key_t ir;
for (i=0;i<16;i++){
er[i] = 0x30 + i;
ir[i] = 0x90 + i;
}
sm_set_er(er);
sm_set_ir(ir);
// set default ER and IR values (should be unique - set by app or sm later using TLV)
sm_er_ir_set_default();
// defaults
sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS
| SM_STK_GENERATION_METHOD_OOB

View File

@ -61,13 +61,15 @@ typedef struct {
void sm_init(void);
/**
* @brief Set secret ER key for key generation as described in Core V4.0, Vol 3, Part G, 5.2.2
* @brief Set secret ER key for key generation as described in Core V4.0, Vol 3, Part G, 5.2.2
* @note If not set and btstack_tlv is configured, ER key is generated and stored in TLV by SM
* @param er
*/
void sm_set_er(sm_key_t er);
/**
* @brief Set secret IR key for key generation as described in Core V4.0, Vol 3, Part G, 5.2.2
* @brief Set secret IR key for key generation as described in Core V4.0, Vol 3, Part G, 5.2.2
* @note If not set and btstack_tlv is configured, IR key is generated and stored in TLV by SM
*/
void sm_set_ir(sm_key_t ir);