OSDN Git Service

Support for H7 function for key derivation
authorJakub Pawlowski <jpawlowski@google.com>
Mon, 20 Mar 2017 22:38:56 +0000 (15:38 -0700)
committerJakub Pawlowski <jpawlowski@google.com>
Sat, 8 Apr 2017 05:22:45 +0000 (05:22 +0000)
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
stack/include/smp_api_types.h
stack/smp/smp_act.cc
stack/smp/smp_int.h
stack/smp/smp_keys.cc
stack/smp/smp_utils.cc

index 2b94c8b..c7bf40e 100644 (file)
@@ -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
index 3e47aad..f300ec4 100644 (file)
@@ -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 */
index 506d6a2..51b8972 100644 (file)
@@ -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)",
index 3d6f4f7..ed22968 100644 (file)
@@ -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,
index 4154fcf..fb77c77 100644 (file)
@@ -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.
  */
index 2539388..f613ed1 100644 (file)
@@ -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);