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
#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
#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 */
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;
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)",
/* 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;
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,
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__);
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;
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__);
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__);
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.
*/
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);