OSDN Git Service

Fix buffer overflow in btif_dm_data_copy
[android-x86/system-bt.git] / stack / smp / smp_act.c
index c8fe9b2..a986cbd 100644 (file)
  *
  ******************************************************************************/
 
+#include <log/log.h>
 #include <string.h>
 #include "device/include/interop.h"
 #include "include/bt_target.h"
 #include "stack/btm/btm_int.h"
 #include "stack/include/l2c_api.h"
+#include "stack/smp/p_256_ecc_pp.h"
 #include "stack/smp/smp_int.h"
 #include "utils/include/bt_utils.h"
 
+extern fixed_queue_t *btu_general_alarm_queue;
+
 #if SMP_INCLUDED == TRUE
 const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
 {
@@ -63,6 +67,42 @@ static bool lmp_version_below(BD_ADDR bda, uint8_t version)
     return acl->lmp_version < version;
 }
 
+static bool pts_test_send_authentication_complete_failure(tSMP_CB *p_cb)
+{
+    uint8_t reason = 0;
+
+    if (p_cb->cert_failure < 2 || p_cb->cert_failure > 6)
+        return false;
+
+    SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
+
+    switch (p_cb->cert_failure)
+    {
+        case 2:
+            reason = SMP_PAIR_AUTH_FAIL;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+        case 3:
+            reason = SMP_PAIR_FAIL_UNKNOWN;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+        case 4:
+            reason = SMP_PAIR_NOT_SUPPORT;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+        case 5:
+            reason = SMP_PASSKEY_ENTRY_FAIL;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+        case 6:
+            reason = SMP_REPEATED_ATTEMPTS;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            break;
+    }
+
+    return true;;
+}
+
 /*******************************************************************************
 ** Function         smp_update_key_mask
 ** Description      This function updates the key mask for sending or receiving.
@@ -358,7 +398,7 @@ void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_LENC_KEYS   le_key;
+    tBTM_LE_KEY_VALUE key;
 
     SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
@@ -367,14 +407,13 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
 
     /* save the DIV and key size information when acting as slave device */
-    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
-    le_key.div =  p_cb->div;
-    le_key.key_size = p_cb->loc_enc_size;
-    le_key.sec_level = p_cb->sec_level;
+    memcpy(key.lenc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    key.lenc_key.div =  p_cb->div;
+    key.lenc_key.key_size = p_cb->loc_enc_size;
+    key.lenc_key.sec_level = p_cb->sec_level;
 
     if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
-        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
-                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &key, TRUE);
 
     SMP_TRACE_WARNING ("%s", __func__);
 
@@ -408,17 +447,17 @@ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_LCSRK_KEYS  key;
+    tBTM_LE_KEY_VALUE  key;
     SMP_TRACE_DEBUG("%s", __func__);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE);
 
     if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb))
     {
-        key.div = p_cb->div;
-        key.sec_level = p_cb->sec_level;
-        key.counter = 0; /* initialize the local counter */
-        memcpy (key.csrk, p_cb->csrk, BT_OCTET16_LEN);
-        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, (tBTM_LE_KEY_VALUE *)&key, TRUE);
+        key.lcsrk_key.div = p_cb->div;
+        key.lcsrk_key.sec_level = p_cb->sec_level;
+        key.lcsrk_key.counter = 0; /* initialize the local counter */
+        memcpy (key.lcsrk_key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, TRUE);
     }
 
     smp_key_distribution_by_transport(p_cb, NULL);
@@ -517,6 +556,9 @@ void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     SMP_TRACE_DEBUG("%s", __func__);
     p_cb->status = *(UINT8 *)p_data;
+
+    /* Cancel pending auth complete timer if set */
+    alarm_cancel(p_cb->delayed_auth_timer_ent);
 }
 
 /*******************************************************************************
@@ -550,6 +592,10 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
         return;
     }
 
+    // PTS Testing failure modes
+    if (pts_test_send_authentication_complete_failure(p_cb))
+        return;
+
     if (p_cb->role == HCI_ROLE_SLAVE)
     {
         if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
@@ -705,6 +751,17 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 
     STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
     STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
+
+    Point pt;
+    memcpy(pt.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
+    memcpy(pt.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
+
+    if (!ECC_ValidatePoint(&pt)) {
+        android_errorWriteLog(0x534e4554, "72377774");
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
     p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
 
     smp_wait_for_both_public_keys(p_cb, NULL);
@@ -770,14 +827,18 @@ void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UINT8 reason = SMP_INVALID_PARAMETERS;
 
     SMP_TRACE_DEBUG("%s", __func__);
-    p_cb->status = *(UINT8 *)p_data;
 
     if (smp_command_has_invalid_parameters(p_cb))
     {
+        if (p_cb->rcvd_cmd_len < 2) {  // 1 (opcode) + 1 (Notif Type) bytes
+            android_errorWriteLog(0x534e4554, "111936834");
+        }
         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
         return;
     }
 
+    p_cb->status = *(UINT8 *)p_data;
+
     if (p != NULL)
     {
         STREAM_TO_UINT8(p_cb->peer_keypress_notification, p);
@@ -954,6 +1015,14 @@ void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UINT8   *p = (UINT8 *)p_data;
 
     SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        uint8_t reason = SMP_INVALID_PARAMETERS;
+        android_errorWriteLog(0x534e4554, "111937065");
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
     STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
 
     smp_key_distribution(p_cb, NULL);
@@ -965,29 +1034,35 @@ void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8   *p = (UINT8 *)p_data;
-    tBTM_LE_PENC_KEYS   le_key;
+    tBTM_LE_KEY_VALUE   le_key;
 
     SMP_TRACE_DEBUG("%s", __func__);
+
+    if (p_cb->rcvd_cmd_len < 11) {  // 1(Code) + 2(EDIV) + 8(Rand)
+        android_errorWriteLog(0x534e4554, "111937027");
+        SMP_TRACE_ERROR("%s: Invalid command length: %d, should be at least 11",
+                        __func__, p_cb->rcvd_cmd_len);
+        return;
+    }
+
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
 
-    STREAM_TO_UINT16(le_key.ediv, p);
-    STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+    STREAM_TO_UINT16(le_key.penc_key.ediv, p);
+    STREAM_TO_ARRAY(le_key.penc_key.rand, p, BT_OCTET8_LEN );
 
     /* store the encryption keys from peer device */
-    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
-    le_key.sec_level = p_cb->sec_level;
-    le_key.key_size  = p_cb->loc_enc_size;
+    memcpy(le_key.penc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    le_key.penc_key.sec_level = p_cb->sec_level;
+    le_key.penc_key.key_size  = p_cb->loc_enc_size;
 
     if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
-        btm_sec_save_le_key(p_cb->pairing_bda,
-                            BTM_LE_KEY_PENC,
-                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &le_key, TRUE);
 
     smp_key_distribution(p_cb, NULL);
 }
 
 /*******************************************************************************
-** Function     smp_proc_enc_info
+** Function     smp_proc_id_info
 ** Description  process identity information from peer device
 *******************************************************************************/
 void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
@@ -995,6 +1070,14 @@ void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UINT8   *p = (UINT8 *)p_data;
 
     SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb)) {
+        uint8_t reason = SMP_INVALID_PARAMETERS;
+        android_errorWriteLog(0x534e4554, "111937065");
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
     STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN);   /* reuse TK for IRK */
     smp_key_distribution_by_transport(p_cb, NULL);
 }
@@ -1006,24 +1089,23 @@ void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8   *p = (UINT8 *)p_data;
-    tBTM_LE_PID_KEYS    pid_key;
+    tBTM_LE_KEY_VALUE    pid_key;
 
     SMP_TRACE_DEBUG("%s", __func__);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
 
-    STREAM_TO_UINT8(pid_key.addr_type, p);
-    STREAM_TO_BDADDR(pid_key.static_addr, p);
-    memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+    STREAM_TO_UINT8(pid_key.pid_key.addr_type, p);
+    STREAM_TO_BDADDR(pid_key.pid_key.static_addr, p);
+    memcpy(pid_key.pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
 
     /* to use as BD_ADDR for lk derived from ltk */
     p_cb->id_addr_rcvd = TRUE;
-    p_cb->id_addr_type = pid_key.addr_type;
-    memcpy(p_cb->id_addr, pid_key.static_addr, BD_ADDR_LEN);
+    p_cb->id_addr_type = pid_key.pid_key.addr_type;
+    memcpy(p_cb->id_addr, pid_key.pid_key.static_addr, BD_ADDR_LEN);
 
     /* store the ID key from peer device */
     if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
-        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
-                            (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, &pid_key, TRUE);
     smp_key_distribution_by_transport(p_cb, NULL);
 }
 
@@ -1033,20 +1115,18 @@ void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_PCSRK_KEYS   le_key;
+    tBTM_LE_KEY_VALUE   le_key;
 
     SMP_TRACE_DEBUG("%s", __func__);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
 
     /* save CSRK to security record */
-    le_key.sec_level = p_cb->sec_level;
-    memcpy (le_key.csrk, p_data, BT_OCTET16_LEN);   /* get peer CSRK */
-    le_key.counter = 0; /* initialize the peer counter */
+    le_key.pcsrk_key.sec_level = p_cb->sec_level;
+    memcpy (le_key.pcsrk_key.csrk, p_data, BT_OCTET16_LEN);   /* get peer CSRK */
+    le_key.pcsrk_key.counter = 0; /* initialize the peer counter */
 
     if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
-        btm_sec_save_le_key(p_cb->pairing_bda,
-                            BTM_LE_KEY_PCSRK,
-                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, &le_key, TRUE);
     smp_key_distribution_by_transport(p_cb, NULL);
 }
 
@@ -1247,7 +1327,6 @@ void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   reason = SMP_SUCCESS;
     SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
                       __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
 
@@ -1269,9 +1348,22 @@ void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
             }
 
             if (p_cb->total_tx_unacked == 0)
-                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-            else
+            {
+                /*
+                 * Instead of declaring authorization complete immediately,
+                 * delay the event from being sent by SMP_DELAYED_AUTH_TIMEOUT_MS.
+                 * This allows the slave to send over Pairing Failed if the
+                 * last key is rejected.  During this waiting window, the
+                 * state should remain in SMP_STATE_BOND_PENDING.
+                 */
+                if (!alarm_is_scheduled(p_cb->delayed_auth_timer_ent)) {
+                    SMP_TRACE_DEBUG("%s delaying auth complete.", __func__);
+                    alarm_set_on_queue(p_cb->delayed_auth_timer_ent, SMP_DELAYED_AUTH_TIMEOUT_MS,
+                                       smp_delayed_auth_complete_timeout, NULL, btu_general_alarm_queue);
+                }
+            } else {
                 p_cb->wait_for_authorization_complete = TRUE;
+            }
         }
     }
 }
@@ -1403,6 +1495,11 @@ void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
         {
             if (smp_request_oob_data(p_cb)) return;
         }
+
+        // PTS Testing failure modes
+        if (pts_test_send_authentication_complete_failure(p_cb))
+            return;
+
         smp_send_pair_rsp(p_cb, NULL);
     }
 }
@@ -1440,8 +1537,6 @@ void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     if (p_cb->total_tx_unacked == 0)
     {
-        /* update connection parameter to remote preferred */
-        L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
         /* process the pairing complete */
         smp_proc_pairing_cmpl(p_cb);
     }
@@ -1480,8 +1575,11 @@ void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    /* disable connection parameter update */
-    L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+    /* Disable L2CAP connection parameter updates while bonding since
+       some peripherals are not able to revert to fast connection parameters
+       during the start of service discovery. Connection paramter updates
+       get enabled again once service discovery completes. */
+    L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, false);
 }
 
 /*******************************************************************************
@@ -1638,6 +1736,14 @@ void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 
     SMP_TRACE_DEBUG("%s start ", __func__);
 
+    // PTS Testing failure modes
+    if (p_cb->cert_failure == 1) {
+        SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
+        reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
     switch(p_cb->selected_association_model)
     {
         case SMP_MODEL_SEC_CONN_JUSTWORKS:
@@ -1671,7 +1777,7 @@ void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
             break;
         case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
         case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
-            if (!smp_check_commitment(p_cb))
+            if (!smp_check_commitment(p_cb) && p_cb->cert_failure != 9)
             {
                 reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
                 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);