From e7f14a682d57811d9df0d64372f222bcc143ec86 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Mon, 20 Mar 2017 15:38:56 -0700 Subject: [PATCH] Support for H7 function for key derivation This change sets bit 5 of the auth req to 1 to display the support for H7 function, for key derivation. Also, it adds the implementation of the h7 function as defined in the spec (ERRATA E7301] H7 is used if both host and remote devices exhibit their support for H7 function in the auth request, else the key derivation falls back to the H6 implementation. The method is similar for derivation from either transports with the only difference being in the first byte of the SAL used in h7. This patch is based on CAF patch by niarora@codeaurora.org 70668ad34ff15d0a53aea612d3c488fa575176ca Test: manual Bug: 35935853 Change-Id: I2fa29b2f3d2b3ac007b2f5f024871f81220237d8 --- stack/include/btm_api_types.h | 11 ++++---- stack/include/smp_api_types.h | 15 ++++++---- stack/smp/smp_act.cc | 13 +++++++-- stack/smp/smp_int.h | 2 ++ stack/smp/smp_keys.cc | 64 +++++++++++++++++++++++++++++++++++++++---- stack/smp/smp_utils.cc | 10 +++++-- 6 files changed, 95 insertions(+), 20 deletions(-) diff --git a/stack/include/btm_api_types.h b/stack/include/btm_api_types.h index 2b94c8bc8..c7bf40e16 100644 --- a/stack/include/btm_api_types.h +++ b/stack/include/btm_api_types.h @@ -1638,12 +1638,13 @@ typedef uint8_t tBTM_LE_KEY_TYPE; typedef uint8_t tBTM_LE_AUTH_REQ; #define BTM_LE_SC_SUPPORT_BIT SMP_SC_SUPPORT_BIT /* (1 << 3) */ #define BTM_LE_KP_SUPPORT_BIT SMP_KP_SUPPORT_BIT /* (1 << 4) */ +#define BTM_LE_H7_SUPPORT_BIT SMP_H7_SUPPORT_BIT /* (1 << 5) */ -#define BTM_LE_AUTH_REQ_SC_ONLY SMP_AUTH_SC_ENC_ONLY /* 1 << 3 */ -#define BTM_LE_AUTH_REQ_SC_BOND SMP_AUTH_SC_GB /* 1001 */ -#define BTM_LE_AUTH_REQ_SC_MITM SMP_AUTH_SC_MITM_NB /* 1100 */ -#define BTM_LE_AUTH_REQ_SC_MITM_BOND SMP_AUTH_SC_MITM_GB /* 1101 */ -#define BTM_LE_AUTH_REQ_MASK SMP_AUTH_MASK /* 0x1D */ +#define BTM_LE_AUTH_REQ_SC_ONLY SMP_AUTH_SC_ENC_ONLY /* 00101000 */ +#define BTM_LE_AUTH_REQ_SC_BOND SMP_AUTH_SC_GB /* 00101001 */ +#define BTM_LE_AUTH_REQ_SC_MITM SMP_AUTH_SC_MITM_NB /* 00101100 */ +#define BTM_LE_AUTH_REQ_SC_MITM_BOND SMP_AUTH_SC_MITM_GB /* 00101101 */ +#define BTM_LE_AUTH_REQ_MASK SMP_AUTH_MASK /* 0x3D */ /* LE security level */ #define BTM_LE_SEC_NONE SMP_SEC_NONE diff --git a/stack/include/smp_api_types.h b/stack/include/smp_api_types.h index 3e47aad01..f300ec46e 100644 --- a/stack/include/smp_api_types.h +++ b/stack/include/smp_api_types.h @@ -128,10 +128,11 @@ typedef uint8_t tSMP_OOB_DATA_TYPE; #define SMP_AUTH_YN_BIT (1 << 2) #define SMP_SC_SUPPORT_BIT (1 << 3) #define SMP_KP_SUPPORT_BIT (1 << 4) +#define SMP_H7_SUPPORT_BIT (1 << 5) #define SMP_AUTH_MASK \ (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT | SMP_SC_SUPPORT_BIT | \ - SMP_KP_SUPPORT_BIT) + SMP_KP_SUPPORT_BIT | SMP_H7_SUPPORT_BIT) #define SMP_AUTH_BOND SMP_AUTH_GEN_BOND @@ -149,18 +150,20 @@ typedef uint8_t tSMP_OOB_DATA_TYPE; #define SMP_AUTH_GB_IOCAP (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT) /* Secure Connections, no MITM, no Bonding */ -#define SMP_AUTH_SC_ENC_ONLY (SMP_SC_SUPPORT_BIT) +#define SMP_AUTH_SC_ENC_ONLY (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT) /* Secure Connections, no MITM, Bonding */ -#define SMP_AUTH_SC_GB (SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND) +#define SMP_AUTH_SC_GB \ + (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND) /* Secure Connections, MITM, no Bonding */ #define SMP_AUTH_SC_MITM_NB \ - (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND) + (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND) /* Secure Connections, MITM, Bonding */ -#define SMP_AUTH_SC_MITM_GB \ - (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_GEN_BOND) +#define SMP_AUTH_SC_MITM_GB \ + (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | \ + SMP_AUTH_GEN_BOND) /* All AuthReq RFU bits are set to 1 - NOTE: reserved bit in Bonding_Flags is * not set */ diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc index 506d6a254..51b8972b7 100644 --- a/stack/smp/smp_act.cc +++ b/stack/smp/smp_act.cc @@ -209,14 +209,16 @@ void smp_send_app_cback(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { p_cb->loc_enc_size = cb_data.io_req.max_key_size; p_cb->local_i_key = cb_data.io_req.init_keys; p_cb->local_r_key = cb_data.io_req.resp_keys; + p_cb->loc_auth_req |= SMP_H7_SUPPORT_BIT; p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK; p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK; SMP_TRACE_WARNING( "for SMP over BR max_key_size: 0x%02x,\ - local_i_key: 0x%02x, local_r_key: 0x%02x", - p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key); + local_i_key: 0x%02x, local_r_key: 0x%02x, p_cb->loc_auth_req: 0x%02x", + p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key, + p_cb->loc_auth_req); smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL); break; @@ -845,6 +847,13 @@ void smp_br_check_authorization_request(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK); } + /* Check if H7 function needs to be used for key derivation*/ + if ((p_cb->loc_auth_req & SMP_H7_SUPPORT_BIT) && + (p_cb->peer_auth_req & SMP_H7_SUPPORT_BIT)) { + p_cb->key_derivation_h7_used = TRUE; + } + SMP_TRACE_DEBUG("%s: use h7 = %d", __func__, p_cb->key_derivation_h7_used); + SMP_TRACE_DEBUG( "%s rcvs upgrades: i_keys=0x%x r_keys=0x%x " "(i-initiator r-responder)", diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h index 3d6f4f72d..ed2296850 100644 --- a/stack/smp/smp_int.h +++ b/stack/smp/smp_int.h @@ -299,6 +299,7 @@ typedef struct { /* either in Secure Connections mode or not at all */ tSMP_ASSO_MODEL selected_association_model; bool le_secure_connections_mode_is_used; + bool key_derivation_h7_used; bool le_sc_kp_notif_is_used; tSMP_SC_KEY_TYPE local_keypress_notification; tSMP_SC_KEY_TYPE peer_keypress_notification; @@ -528,6 +529,7 @@ extern bool smp_calculate_f6(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* r, uint8_t* iocap, uint8_t* a1, uint8_t* a2, uint8_t* f3); extern bool smp_calculate_h6(uint8_t* w, uint8_t* keyid, uint8_t* h2); +extern bool smp_calculate_h7(uint8_t* salt, uint8_t* w, uint8_t* h2); #if (SMP_DEBUG == TRUE) extern void smp_debug_print_nbyte_little_endian(uint8_t* p, const char* key_name, diff --git a/stack/smp/smp_keys.cc b/stack/smp/smp_keys.cc index 4154fcf30..fb77c779c 100644 --- a/stack/smp/smp_keys.cc +++ b/stack/smp/smp_keys.cc @@ -1634,6 +1634,8 @@ bool smp_calculate_link_key_from_long_term_key(tSMP_CB* p_cb) { tBTM_SEC_DEV_REC* p_dev_rec; BD_ADDR bda_for_lk; tBLE_ADDR_TYPE conn_addr_type; + BT_OCTET16 salt = {0x31, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; SMP_TRACE_DEBUG("%s", __func__); @@ -1659,8 +1661,11 @@ bool smp_calculate_link_key_from_long_term_key(tSMP_CB* p_cb) { BT_OCTET16 intermediate_link_key; bool ret = true; - ret = smp_calculate_h6(p_cb->ltk, (uint8_t*)"1pmt" /* reversed "tmp1" */, - intermediate_link_key); + if (p_cb->key_derivation_h7_used) + ret = smp_calculate_h7((uint8_t*)salt, p_cb->ltk, intermediate_link_key); + else + ret = smp_calculate_h6(p_cb->ltk, (uint8_t*)"1pmt" /* reversed "tmp1" */, + intermediate_link_key); if (!ret) { SMP_TRACE_ERROR("%s failed to derive intermediate_link_key", __func__); return ret; @@ -1724,6 +1729,8 @@ bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb) { bool ret = true; tBTM_SEC_DEV_REC* p_dev_rec; uint8_t rev_link_key[16]; + BT_OCTET16 salt = {0x32, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; SMP_TRACE_DEBUG("%s", __func__); @@ -1754,9 +1761,14 @@ bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb) { REVERSE_ARRAY_TO_STREAM(p1, p2, 16); BT_OCTET16 intermediate_long_term_key; - /* "tmp2" obtained from the spec */ - ret = smp_calculate_h6(rev_link_key, (uint8_t*)"2pmt" /* reversed "tmp2" */, - intermediate_long_term_key); + if (p_cb->key_derivation_h7_used) { + ret = smp_calculate_h7((uint8_t*)salt, rev_link_key, + intermediate_long_term_key); + } else { + /* "tmp2" obtained from the spec */ + ret = smp_calculate_h6(rev_link_key, (uint8_t*)"2pmt" /* reversed "tmp2" */, + intermediate_long_term_key); + } if (!ret) { SMP_TRACE_ERROR("%s failed to derive intermediate_long_term_key", __func__); @@ -1849,6 +1861,48 @@ bool smp_calculate_h6(uint8_t* w, uint8_t* keyid, uint8_t* c) { return ret; } +/******************************************************************************* +** +** Function smp_calculate_h7 +** +** Description The function calculates +** C = h7(SALT, W) = AES-CMAC (W) +** SALT +** where +** input: W is 128 bit, +** SALT is 128 bit, +** output: C is 128 bit. +** +** Returns FALSE if out of resources, TRUE in other cases. +** +** Note The LSB is the first octet, the MSB is the last octet of +** the AES-CMAC input/output stream. +** +*******************************************************************************/ +bool smp_calculate_h7(uint8_t* salt, uint8_t* w, uint8_t* c) { + SMP_TRACE_DEBUG("%s", __FUNCTION__); + + uint8_t key[BT_OCTET16_LEN]; + uint8_t* p = key; + ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN); + + uint8_t msg_len = BT_OCTET16_LEN /* msg size */; + uint8_t msg[BT_OCTET16_LEN]; + p = msg; + ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN); + + bool ret = true; + uint8_t cmac[BT_OCTET16_LEN]; + if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac)) { + SMP_TRACE_ERROR("%s failed", __FUNCTION__); + ret = false; + } + + p = c; + ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN); + return ret; +} + /** * This function generates nonce. */ diff --git a/stack/smp/smp_utils.cc b/stack/smp/smp_utils.cc index 253938802..f613ed190 100644 --- a/stack/smp/smp_utils.cc +++ b/stack/smp/smp_utils.cc @@ -1175,8 +1175,14 @@ tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB* p_cb) { p_cb->le_secure_connections_mode_is_used = true; } - SMP_TRACE_DEBUG("use_sc_process = %d", - p_cb->le_secure_connections_mode_is_used); + if ((p_cb->peer_auth_req & SMP_H7_SUPPORT_BIT) && + (p_cb->loc_auth_req & SMP_H7_SUPPORT_BIT)) { + p_cb->key_derivation_h7_used = TRUE; + } + + SMP_TRACE_DEBUG("use_sc_process = %d, h7 use = %d", + p_cb->le_secure_connections_mode_is_used, + p_cb->key_derivation_h7_used); if (p_cb->le_secure_connections_mode_is_used) { model = smp_select_association_model_secure_connections(p_cb); -- 2.11.0