sm: add sm_generate_sc_oob_data

This commit is contained in:
Matthias Ringwald 2018-04-02 21:53:17 +02:00
parent 65a9a04ea0
commit c59d0c922e
2 changed files with 78 additions and 0 deletions

View File

@ -187,6 +187,16 @@ typedef enum {
SM_STATE_VAR_DHKEY_COMMAND_RECEIVED = 1 << 2,
} sm_state_var_t;
typedef enum {
SM_SC_OOB_IDLE,
SM_SC_OOB_W2_GET_RANDOM_1,
SM_SC_OOB_W4_RANDOM_1,
SM_SC_OOB_W2_GET_RANDOM_2,
SM_SC_OOB_W4_RANDOM_2,
SM_SC_OOB_W2_CALC_CONFIRM,
SM_SC_OOB_W4_CONFIRM,
} sm_sc_oob_state_t;
typedef uint8_t sm_key24_t[3];
typedef uint8_t sm_key56_t[7];
typedef uint8_t sm_key256_t[32];
@ -214,6 +224,12 @@ static uint8_t sm_reconstruct_ltk_without_le_device_db_entry;
static uint8_t sm_have_ec_keypair;
#endif
#ifdef ENABLE_LE_SECURE_CONNECTIONS
static uint8_t sm_sc_oob_random[16];
static void (*sm_sc_oob_callback)(const uint8_t * confirm_value, const uint8_t * random_value);
static sm_sc_oob_state_t sm_sc_oob_state;
#endif
// 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;
@ -1484,6 +1500,12 @@ static void sm_sc_cmac_done(uint8_t * hash){
log_info("sm_sc_cmac_done: ");
log_info_hexdump(hash, 16);
if (sm_sc_oob_state == SM_SC_OOB_W4_CONFIRM){
sm_sc_oob_state = SM_SC_OOB_IDLE;
(*sm_sc_oob_callback)(sm_sc_oob_random, hash);
return;
}
sm_connection_t * sm_conn = sm_cmac_connection;
sm_cmac_connection = NULL;
#ifdef ENABLE_CLASSIC
@ -2064,6 +2086,28 @@ static void sm_run(void){
}
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
// TODO: we need to verify that nobody's already waiting for random data
switch (sm_sc_oob_state){
case SM_SC_OOB_W2_GET_RANDOM_1:
sm_sc_oob_state = SM_SC_OOB_W4_RANDOM_1;
sm_random_start(NULL);
return;
case SM_SC_OOB_W2_GET_RANDOM_2:
sm_sc_oob_state = SM_SC_OOB_W4_RANDOM_2;
sm_random_start(NULL);
return;
case SM_SC_OOB_W2_CALC_CONFIRM:
if (!sm_cmac_ready()) break;
if (ec_key_generation_state != EC_KEY_GENERATION_DONE) break;
sm_sc_oob_state = SM_SC_OOB_W4_CONFIRM;
f4_engine(NULL, ec_q, ec_q, sm_sc_oob_random, 0);
break;
default:
break;
}
#endif
// handle basic actions that don't requires the full context
hci_connections_get_iterator(&it);
while((sm_active_connection_handle == HCI_CON_HANDLE_INVALID) && btstack_linked_list_iterator_has_next(&it)){
@ -3047,6 +3091,21 @@ static void sm_handle_random_result(uint8_t * data){
break;
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
switch (sm_sc_oob_state){
case SM_SC_OOB_W4_RANDOM_1:
memcpy(&sm_sc_oob_random[0], data, 8);
sm_sc_oob_state = SM_SC_OOB_W2_GET_RANDOM_2;
return;
case SM_SC_OOB_W4_RANDOM_2:
memcpy(&sm_sc_oob_random[8], data, 8);
sm_sc_oob_state = SM_SC_OOB_W2_CALC_CONFIRM;
return;
default:
break;
}
#endif
// retrieve sm_connection provided to sm_random_start
sm_connection_t * connection = (sm_connection_t *) sm_random_context;
if (!connection) return;
@ -4323,6 +4382,16 @@ void sm_keypress_notification(hci_con_handle_t con_handle, uint8_t action){
sm_run();
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
uint8_t sm_generate_sc_oob_data(void (*callback)(const uint8_t * confirm_value, const uint8_t * random_value)){
if (sm_sc_oob_state != SM_SC_OOB_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
sm_sc_oob_callback = callback;
sm_sc_oob_state = SM_SC_OOB_W2_GET_RANDOM_1;
sm_run();
return 0;
}
#endif
/**
* @brief Identify device in LE Device DB
* @param handle

View File

@ -242,6 +242,15 @@ void sm_use_fixed_passkey_in_display_role(uint32_t passkey);
*/
void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow);
/**
* @brief Generate OOB data for LE Secure Connections
* @note This generates a 128 bit random number ra and then calculates Ca = f4(PKa, PKa, ra, 0)
* New OOB data should be generated for each pairing
* @param callback
* @returns status
*/
uint8_t sm_generate_sc_oob_data(void (*callback)(const uint8_t * confirm_value, const uint8_t * random_value));
/* API_END */
// PTS testing