sm: implement h7 ctkd

Set CT2 in AuthReq if Bonding+SC+CTKD
This commit is contained in:
Matthias Ringwald 2020-10-08 22:38:01 +02:00
parent 7ece0eaa04
commit 57132f1279
5 changed files with 80 additions and 16 deletions

View File

@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- GAP: add `gap_get_link_key_for_bd_addr`
- SM: support h7 for CTKD
### Changed
- SM: Cross-Transport Key Derivation requires `ENABLE_CROSS_TRANSPORT_KEY_DERIVATION` now

View File

@ -1125,7 +1125,14 @@ static void sm_init_setup(sm_connection_t * sm_conn){
sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
}
uint8_t auth_req = sm_auth_req;
uint8_t auth_req = sm_auth_req & ~SM_AUTHREQ_CT2;
#ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
// set CT2 if SC + Bonding + CTKD
const uint8_t auth_req_for_ct2 = SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING;
if ((auth_req & auth_req_for_ct2) == auth_req_for_ct2){
auth_req |= SM_AUTHREQ_CT2;
}
#endif
sm_pairing_packet_set_io_capability(*local_packet, sm_io_capabilities);
sm_pairing_packet_set_oob_data_flag(*local_packet, setup->sm_have_oob_data);
sm_pairing_packet_set_auth_req(*local_packet, auth_req);
@ -1532,11 +1539,11 @@ static void sm_sc_cmac_done(uint8_t * hash){
}
break;
#ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
case SM_SC_W4_CALCULATE_H6_ILK:
case SM_SC_W4_CALCULATE_ILK:
(void)memcpy(setup->sm_t, hash, 16);
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_H6_BR_EDR_LINK_KEY;
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY;
break;
case SM_SC_W4_CALCULATE_H6_BR_EDR_LINK_KEY:
case SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY:
reverse_128(hash, setup->sm_t);
link_key_type = sm_conn->sm_connection_authenticated ?
AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256 : UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
@ -1801,7 +1808,7 @@ static void sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn){
//
// Link Key Conversion Function h6
//
// h6(W, keyID) = AES-CMACW(keyID)
// h6(W, keyID) = AES-CMAC_W(keyID)
// - W is 128 bits
// - keyID is 32 bits
static void h6_engine(sm_connection_t * sm_conn, const sm_key_t w, const uint32_t key_id){
@ -1814,11 +1821,27 @@ static void h6_engine(sm_connection_t * sm_conn, const sm_key_t w, const uint32_
log_info_hexdump(sm_cmac_sc_buffer, message_len);
sm_cmac_message_start(w, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
}
//
// Link Key Conversion Function h7
//
// h7(SALT, W) = AES-CMAC_SALT(W)
// - SALT is 128 bits
// - W is 128 bits
static void h7_engine(sm_connection_t * sm_conn, const sm_key_t salt, const sm_key_t w) {
const uint16_t message_len = 16;
sm_cmac_connection = sm_conn;
log_info("h7 key");
log_info_hexdump(salt, 16);
log_info("h7 message");
log_info_hexdump(w, 16);
sm_cmac_message_start(salt, message_len, w, &sm_sc_cmac_done);
}
// For SC, setup->sm_local_ltk holds full LTK (sm_ltk is already truncated)
// Errata Service Release to the Bluetooth Specification: ESR09
// E6405 Cross transport key derivation from a key of size less than 128 bits
// "Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
static void h6_calculate_ilk(sm_connection_t * sm_conn){
h6_engine(sm_conn, setup->sm_local_ltk, 0x746D7031); // "tmp1"
}
@ -1827,6 +1850,10 @@ static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
h6_engine(sm_conn, setup->sm_t, 0x6c656272); // "lebr"
}
static void h7_calculate_ilk(sm_connection_t * sm_conn){
const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31}; // "tmp1"
h7_engine(sm_conn, salt, setup->sm_local_ltk);
}
#endif
#endif
@ -2356,16 +2383,21 @@ static void sm_run(void){
g2_calculate(connection);
break;
#ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
case SM_SC_W2_CALCULATE_H6_ILK:
case SM_SC_W2_CALCULATE_ILK_USING_H6:
if (!sm_cmac_ready()) break;
connection->sm_engine_state = SM_SC_W4_CALCULATE_H6_ILK;
connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
h6_calculate_ilk(connection);
break;
case SM_SC_W2_CALCULATE_H6_BR_EDR_LINK_KEY:
case SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY:
if (!sm_cmac_ready()) break;
connection->sm_engine_state = SM_SC_W4_CALCULATE_H6_BR_EDR_LINK_KEY;
connection->sm_engine_state = SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY;
h6_calculate_br_edr_link_key(connection);
break;
case SM_SC_W2_CALCULATE_ILK_USING_H7:
if (!sm_cmac_ready()) break;
connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
h7_calculate_ilk(connection);
break;
#endif
#endif
@ -2975,7 +3007,8 @@ static void sm_handle_encryption_result_enc_csrk(void *arg){
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
} else {
if (sm_ctkd_from_le(connection)){
connection->sm_engine_state = SM_SC_W2_CALCULATE_H6_ILK;
bool use_h7 = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_CT2) != 0;
connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
} else {
sm_master_pairing_success(connection);
}
@ -4028,7 +4061,8 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
if (IS_RESPONDER(sm_conn->sm_role)){
if (sm_ctkd_from_le(sm_conn)){
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_H6_ILK;
bool use_h7 = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_CT2) != 0;
sm_conn->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
} else {
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
sm_notify_client_status_reason(sm_conn, ERROR_CODE_SUCCESS, 0);

View File

@ -702,6 +702,7 @@ typedef enum {
#define SM_AUTHREQ_MITM_PROTECTION 0x04
#define SM_AUTHREQ_SECURE_CONNECTION 0x08
#define SM_AUTHREQ_KEYPRESS 0x10
#define SM_AUTHREQ_CT2 0x20
// Key distribution flags used by spec
#define SM_KEYDIST_ENC_KEY 0x01

View File

@ -379,10 +379,11 @@ typedef enum {
SM_SC_SEND_DHKEY_CHECK_COMMAND,
SM_SC_W4_DHKEY_CHECK_COMMAND,
SM_SC_W4_LTK_REQUEST_SC,
SM_SC_W2_CALCULATE_H6_ILK,
SM_SC_W4_CALCULATE_H6_ILK,
SM_SC_W2_CALCULATE_H6_BR_EDR_LINK_KEY,
SM_SC_W4_CALCULATE_H6_BR_EDR_LINK_KEY,
SM_SC_W2_CALCULATE_ILK_USING_H6,
SM_SC_W2_CALCULATE_ILK_USING_H7,
SM_SC_W4_CALCULATE_ILK,
SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY,
SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY,
} security_manager_state_t;
typedef enum {

View File

@ -62,6 +62,11 @@ const char * h6_key_string = "ec0234a3 57c8ad05 341010a6 0a397d9b";
const char * h6_key_id_string = "6c656272";
const char * h6_cmac_string = "2d9ae102 e76dc91c e8d3a9e2 80b16399";
// h7
const char * h7_key_string = "ec0234a3 57c8ad05 341010a6 0a397d9b";
const char * h7_cmac_string = "fb173597 c6a3c0ec d2998c2a 75a57011";
static uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
}
@ -204,7 +209,7 @@ static uint32_t g2(const sm_key256_t u, const sm_key256_t v, const sm_key_t x, c
return big_endian_read_32(cmac, 12);
}
// h6(W, keyID) = AES-CMACW(keyID)
// h6(W, keyID) = AES-CMAC_W(keyID)
// - W is 128 bits
// - keyID is 32 bits
static void h6(sm_key_t res, const sm_key_t w, const uint32_t key_id){
@ -213,6 +218,14 @@ static void h6(sm_key_t res, const sm_key_t w, const uint32_t key_id){
aes_cmac(res, w, key_id_buffer, 4);
}
// h7(SALT, W) = AES-CMAC_SALT(W)
// - SALT is 128 bit
// - W is 128 bits
static void h7(sm_key_t res, const sm_key_t salt, const sm_key_t w){
uint8_t key_id_buffer[4];
aes_cmac(res, salt, w, 16);
}
int main(void){
sm_key_t key, k0, k1, k2, zero;
memset(zero, 0, 16);
@ -327,4 +340,18 @@ int main(void){
} else {
printf("CMAC correct!\n");
}
// validate h7
printf("-- verify h7\n");
sm_key_t h7_key, h7_res, h7_cmac;
const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31 }; // "tmp1"
parse_hex(h7_key, h7_key_string);
parse_hex(h7_cmac, h7_cmac_string);
h7(h7_res, salt, h7_key);
hexdump2(h7_res, 16);
if (memcmp(h7_res, h7_cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
}