mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-24 21:39:55 +00:00
sm: support SC Passkey Entry
This commit is contained in:
parent
446a8c36fb
commit
45a61d50fd
@ -101,7 +101,10 @@ static void le_counter_setup(void){
|
||||
sm_init();
|
||||
sm_event_callback_registration.callback = &packet_handler;
|
||||
sm_add_event_handler(&sm_event_callback_registration);
|
||||
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
|
||||
// Numeric Comparison
|
||||
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
|
||||
// Passkey entry initiator enter, responder displays
|
||||
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
|
||||
#endif
|
||||
@ -179,7 +182,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
break;
|
||||
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
|
||||
printf("LE Secure Connection - Numeric Comparison: %u\n", sm_event_passkey_display_number_get_passkey(packet));
|
||||
sm_just_works_confirm(sm_event_passkey_display_number_get_handle(packet));
|
||||
// sm_just_works_confirm(sm_event_passkey_display_number_get_handle(packet));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
70
src/ble/sm.c
70
src/ble/sm.c
@ -260,6 +260,7 @@ typedef struct sm_setup_context {
|
||||
sm_key_t sm_local_dhkey_check;
|
||||
sm_key_t sm_ra;
|
||||
sm_key_t sm_rb;
|
||||
uint8_t sm_passkey_bit;
|
||||
#endif
|
||||
|
||||
// Phase 3
|
||||
@ -1638,18 +1639,47 @@ static void sm_run(void){
|
||||
reverse_256(value, &buffer[33]);
|
||||
#endif
|
||||
// TODO: use random generator to generate nonce
|
||||
|
||||
// generate 128-bit nonce
|
||||
int i;
|
||||
for (i=0;i<16;i++){
|
||||
setup->sm_local_nonce[i] = rand() & 0xff;
|
||||
}
|
||||
|
||||
// stk generation method
|
||||
// passkey entry: notify app to show passkey or to request passkey
|
||||
switch (setup->sm_stk_generation_method){
|
||||
case JUST_WORKS:
|
||||
case NK_BOTH_INPUT:
|
||||
if (connection->sm_role){
|
||||
connection->sm_engine_state = SM_PH2_SEND_CONFIRMATION;
|
||||
} else {
|
||||
// TODO:
|
||||
log_error("SC, next state initiator, send local nonce");
|
||||
}
|
||||
break;
|
||||
case PK_INIT_INPUT:
|
||||
case PK_RESP_INPUT:
|
||||
case OK_BOTH_INPUT:
|
||||
// hack for testing: assume user entered '000000'
|
||||
// memset(setup->sm_tk, 0, 16);
|
||||
memcpy(setup->sm_ra, setup->sm_tk, 16);
|
||||
memcpy(setup->sm_rb, setup->sm_tk, 16);
|
||||
setup->sm_passkey_bit = 0;
|
||||
if (connection->sm_role){
|
||||
// responder
|
||||
connection->sm_engine_state = SM_PH2_W4_CONFIRMATION;
|
||||
} else {
|
||||
// initiator
|
||||
connection->sm_engine_state = SM_PH2_SEND_CONFIRMATION;
|
||||
}
|
||||
sm_trigger_user_response(connection);
|
||||
break;
|
||||
case OOB:
|
||||
// TODO: implement SC OOB
|
||||
break;
|
||||
}
|
||||
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||
sm_timeout_reset(connection);
|
||||
break;
|
||||
@ -1658,11 +1688,19 @@ static void sm_run(void){
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_PAIRING_CONFIRM;
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
uint8_t z = 0;
|
||||
if (setup->sm_stk_generation_method != JUST_WORKS && setup->sm_stk_generation_method != NK_BOTH_INPUT){
|
||||
// some form of passkey
|
||||
uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
|
||||
z = 0x80 | ((pk >> setup->sm_passkey_bit) & 1);
|
||||
setup->sm_passkey_bit++;
|
||||
}
|
||||
|
||||
// TODO: use AES Engine to calculate commitment value using f4
|
||||
uint8_t value[32];
|
||||
mbedtls_mpi_write_binary(&le_keypair.Q.X, value, sizeof(value));
|
||||
sm_key_t confirm_value;
|
||||
f4(confirm_value, value, setup->sm_peer_qx, setup->sm_local_nonce, 0);
|
||||
f4(confirm_value, value, setup->sm_peer_qx, setup->sm_local_nonce, z);
|
||||
reverse_128(confirm_value, &buffer[1]);
|
||||
#endif
|
||||
if (connection->sm_role){
|
||||
@ -1679,6 +1717,16 @@ static void sm_run(void){
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_PAIRING_RANDOM;
|
||||
reverse_128(setup->sm_local_nonce, &buffer[1]);
|
||||
|
||||
if (setup->sm_stk_generation_method != JUST_WORKS && setup->sm_stk_generation_method != NK_BOTH_INPUT && setup->sm_passkey_bit < 20){
|
||||
if (connection->sm_role){
|
||||
// responder
|
||||
connection->sm_engine_state = SM_PH2_W4_CONFIRMATION;
|
||||
} else {
|
||||
// initiator
|
||||
// TODO: next initiator state
|
||||
}
|
||||
} else {
|
||||
if (connection->sm_role){
|
||||
// responder
|
||||
connection->sm_engine_state = SM_PH2_W4_DHKEY_CHECK_COMMAND;
|
||||
@ -1695,6 +1743,7 @@ static void sm_run(void){
|
||||
// TODO: next initiator state
|
||||
// connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_RANDOM;
|
||||
}
|
||||
}
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||
sm_timeout_reset(connection);
|
||||
break;
|
||||
@ -1795,7 +1844,7 @@ static void sm_run(void){
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
|
||||
sm_timeout_reset(connection);
|
||||
// SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
|
||||
if (setup->sm_stk_generation_method != NK_BOTH_INPUT){
|
||||
if (setup->sm_stk_generation_method == JUST_WORKS){
|
||||
sm_trigger_user_response(connection);
|
||||
}
|
||||
return;
|
||||
@ -2626,6 +2675,23 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
sm_conn->sm_engine_state = SM_PH2_SEND_PUBLIC_KEY_COMMAND;
|
||||
break;
|
||||
|
||||
case SM_PH2_W4_CONFIRMATION:
|
||||
if (packet[0] != SM_CODE_PAIRING_CONFIRM){
|
||||
sm_pdu_received_in_wrong_state(sm_conn);
|
||||
break;
|
||||
}
|
||||
// received confirm value
|
||||
reverse_128(&packet[1], setup->sm_peer_confirm);
|
||||
|
||||
if (sm_conn->sm_role){
|
||||
// responder
|
||||
sm_conn->sm_engine_state = SM_PH2_SEND_CONFIRMATION;
|
||||
} else {
|
||||
// initiator
|
||||
// TODO: implement initiator role
|
||||
}
|
||||
break;
|
||||
|
||||
case SM_PH2_W4_PAIRING_RANDOM:
|
||||
if (packet[0] != SM_CODE_PAIRING_RANDOM){
|
||||
sm_pdu_received_in_wrong_state(sm_conn);
|
||||
|
Loading…
x
Reference in New Issue
Block a user