Merge branch 'dev/10/fp2/security-aosp-qt-release' into int/10/fp2

* dev/10/fp2/security-aosp-qt-release:
  The length of a packet should be non-zero

Change-Id: Ia4743ca82115c226ac37320a08b0eaff785c033a
diff --git a/src/nfa/dm/nfa_dm_discover.cc b/src/nfa/dm/nfa_dm_discover.cc
index 3414c91..8e5cd5c 100644
--- a/src/nfa/dm/nfa_dm_discover.cc
+++ b/src/nfa/dm/nfa_dm_discover.cc
@@ -76,7 +76,6 @@
 
 static nfa_dm_p2p_prio_logic_t p2p_prio_logic_data;
 
-static void nfa_dm_send_tag_deselect_cmd(tNFA_NFC_PROTOCOL protocol);
 
 /*******************************************************************************
 **
@@ -2139,14 +2138,6 @@
 
   switch (event) {
     case NFA_DM_RF_DEACTIVATE_CMD:
-      if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
-        if ((nfa_dm_cb.disc_cb.activated_rf_interface == NFC_INTERFACE_FRAME) &&
-            (p_data->deactivate_type == NFC_DEACTIVATE_TYPE_SLEEP)) {
-          /* NCI 2.0- DH is responsible for sending deactivation commands before
-           * RF_DEACTIVATE_CMD */
-          nfa_dm_send_tag_deselect_cmd(nfa_dm_cb.disc_cb.activated_protocol);
-        }
-      }
 
       if (nfa_dm_cb.disc_cb.activated_protocol == NCI_PROTOCOL_MIFARE) {
         nfa_dm_cb.disc_cb.deact_pending = true;
@@ -2201,6 +2192,9 @@
       }
       if (p_data->nfc_discover.deactivate.reason !=
           NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
+        /* count for number of times deactivate cmd sent */
+        nfa_dm_cb.deactivate_cmd_retry_count = 0;
+
         sleep_wakeup_event = true;
         nfa_dm_disc_notify_deactivation(NFA_DM_RF_DEACTIVATE_NTF,
                                         &(p_data->nfc_discover));
@@ -2210,8 +2204,7 @@
            NFC_DEACTIVATE_TYPE_SLEEP_AF)) {
         if (p_data->nfc_discover.deactivate.reason !=
             NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
-          /* count for number of times deactivate cmd sent */
-          nfa_dm_cb.deactivate_cmd_retry_count = 0;
+
           nfa_dm_disc_new_state(NFA_DM_RFST_W4_HOST_SELECT);
         }
         if (old_sleep_wakeup_flag) {
@@ -2246,7 +2239,6 @@
                 (!nfa_dm_cb.disc_cb.deact_pending)) {
               nfa_dm_send_deactivate_cmd(NFA_DEACTIVATE_TYPE_DISCOVERY);
             }
-            nfa_dm_cb.deactivate_cmd_retry_count = 0;
           } else {
             nfa_dm_cb.deactivate_cmd_retry_count++;
             nfa_dm_send_deactivate_cmd(p_data->nfc_discover.deactivate.type);
@@ -2259,6 +2251,24 @@
       } else if (p_data->nfc_discover.deactivate.type ==
                  NFC_DEACTIVATE_TYPE_DISCOVERY) {
         nfa_dm_disc_new_state(NFA_DM_RFST_DISCOVERY);
+        /* if deactivation type is discovery and comes after 3 tentatives of
+         * unsuccessful deactivation to sleep then reset the counter and  notify
+         * upper layer.
+         *
+         */
+        if (nfa_dm_cb.deactivate_cmd_retry_count == 3) {
+          nfa_dm_cb.deactivate_cmd_retry_count = 0;
+          DLOG_IF(INFO, nfc_debug_enabled)
+              << __func__
+              << StringPrintf(
+                     " NFA_DM_RF_DEACTIVATE_NTF to discovery after 3 attempt "
+                     "of deactivate (sleep)");
+          if (p_data->nfc_discover.deactivate.reason ==
+              NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
+            nfa_dm_disc_notify_deactivation(NFA_DM_RF_DEACTIVATE_NTF,
+                                            &(p_data->nfc_discover));
+          }
+        }
         if (nfa_dm_cb.disc_cb.disc_flags & NFA_DM_DISC_FLAGS_STOPPING) {
           /* stop discovery */
           NFC_Deactivate(NFA_DEACTIVATE_TYPE_IDLE);
@@ -3056,40 +3066,3 @@
   memset(&p2p_prio_logic_data, 0x00, sizeof(nfa_dm_p2p_prio_logic_t));
 }
 
-/*******************************************************************************
-**
-** Function         nfa_dm_send_tag_deselect_cmd
-**
-** Description      Send command to send tag in sleep state
-**
-** Returns          void
-**
-*******************************************************************************/
-static void nfa_dm_send_tag_deselect_cmd(tNFA_NFC_PROTOCOL protocol) {
-  NFC_HDR* p_msg;
-  uint8_t* p;
-
-  DLOG_IF(INFO, nfc_debug_enabled)
-      << StringPrintf("nfa_dm_send_tag_deselect_cmd");
-  p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
-
-  if (p_msg) {
-    if (protocol == NFC_PROTOCOL_ISO_DEP) {
-      /* send one byte of 0xc2 as as deselect command to Tag */
-      p_msg->len = 1;
-      p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
-      p = (uint8_t*)(p_msg + 1) + p_msg->offset;
-      *p = NFA_RW_TAG_DESELECT_CMD;
-    } else if (protocol == NFC_PROTOCOL_T2T) {
-      p_msg->len = NFA_RW_TAG_SLP_REQ_LEN;
-      p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
-      p = (uint8_t*)(p_msg + 1) + p_msg->offset;
-      memcpy((uint8_t*)(p_msg + 1) + p_msg->offset, NFA_RW_TAG_SLP_REQ,
-             p_msg->len);
-    } else {
-      GKI_freebuf(p_msg);
-      return;
-    }
-    NFC_SendData(NFC_RF_CONN_ID, p_msg);
-  }
-}
diff --git a/src/nfa/dm/nfa_dm_ndef.cc b/src/nfa/dm/nfa_dm_ndef.cc
index e5361cd..48aa844 100644
--- a/src/nfa/dm/nfa_dm_ndef.cc
+++ b/src/nfa/dm/nfa_dm_ndef.cc
@@ -270,8 +270,9 @@
             /* If absolute URI, then compare URI for match (skip over uri_id in
              * ndef payload) */
             if ((p_cb->p_ndef_handler[i]->uri_id != NFA_NDEF_URI_ID_ABSOLUTE) ||
-                (memcmp(&p_payload[1], p_cb->p_ndef_handler[i]->name,
-                        p_cb->p_ndef_handler[i]->name_len) == 0)) {
+                ((payload_len > p_cb->p_ndef_handler[i]->name_len) &&
+                 (memcmp(&p_payload[1], p_cb->p_ndef_handler[i]->name,
+                         p_cb->p_ndef_handler[i]->name_len) == 0))) {
               /* Handler found. */
               break;
             }
@@ -284,6 +285,9 @@
             /* Handler is absolute URI but NDEF is using prefix abrieviation.
              * Compare URI prefix */
             if ((p_payload[0] < NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) &&
+                strlen(
+                    (const char*)nfa_dm_ndef_wkt_uri_str_tbl[p_payload[0]]) >=
+                    p_cb->p_ndef_handler[i]->name_len &&
                 (memcmp(p_cb->p_ndef_handler[i]->name,
                         (char*)nfa_dm_ndef_wkt_uri_str_tbl[p_payload[0]],
                         p_cb->p_ndef_handler[i]->name_len) == 0)) {
@@ -300,6 +304,8 @@
              * URI. Compare URI prefix */
             if ((p_cb->p_ndef_handler[i]->uri_id <
                  NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) &&
+                payload_len > strlen((const char*)nfa_dm_ndef_wkt_uri_str_tbl
+                                         [p_cb->p_ndef_handler[i]->uri_id]) &&
                 (memcmp(&p_payload[1],
                         nfa_dm_ndef_wkt_uri_str_tbl[p_cb->p_ndef_handler[i]
                                                         ->uri_id],
diff --git a/src/nfa/hci/nfa_hci_act.cc b/src/nfa/hci/nfa_hci_act.cc
index 4ad9754..fbc4fbf 100644
--- a/src/nfa/hci/nfa_hci_act.cc
+++ b/src/nfa/hci/nfa_hci_act.cc
@@ -1413,7 +1413,7 @@
             /* Something wrong, NVRAM data could be corrupt or first start with
              * default session id */
             nfa_hciu_send_clear_all_pipe_cmd();
-            nfa_hci_cb.b_hci_netwk_reset = true;
+            nfa_hci_cb.b_hci_new_sessionId = true;
             if (data_len < NFA_HCI_SESSION_ID_LEN) {
               android_errorWriteLog(0x534e4554, "124524315");
             }
@@ -1423,9 +1423,15 @@
 
       case NFA_HCI_ANY_OPEN_PIPE:
         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED;
-
         if (nfa_hci_cb.b_hci_netwk_reset) {
+          /* Something wrong, NVRAM data could be corrupt or first start with
+           * default session id */
+          nfa_hciu_send_clear_all_pipe_cmd();
           nfa_hci_cb.b_hci_netwk_reset = false;
+          nfa_hci_cb.b_hci_new_sessionId = true;
+        } else if (nfa_hci_cb.b_hci_new_sessionId) {
+          nfa_hci_cb.b_hci_new_sessionId = false;
+
           /* Session ID is reset, Set New session id */
           memcpy(
               &nfa_hci_cb.cfg.admin_gate.session_id[NFA_HCI_SESSION_ID_LEN / 2],
diff --git a/src/nfa/hci/nfa_hci_main.cc b/src/nfa/hci/nfa_hci_main.cc
index d6667e1..b4c43be 100644
--- a/src/nfa/hci/nfa_hci_main.cc
+++ b/src/nfa/hci/nfa_hci_main.cc
@@ -741,11 +741,26 @@
   p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
   pkt_len = p_pkt->len;
 
+  if (pkt_len < 1) {
+    LOG(ERROR) << StringPrintf("Insufficient packet length! Dropping :%u bytes",
+                               pkt_len);
+    /* release GKI buffer */
+    GKI_freebuf(p_pkt);
+    return;
+  }
+
   chaining_bit = ((*p) >> 0x07) & 0x01;
   pipe = (*p++) & 0x7F;
   if (pkt_len != 0) pkt_len--;
 
   if (nfa_hci_cb.assembling == false) {
+    if (pkt_len < 1) {
+      LOG(ERROR) << StringPrintf(
+          "Insufficient packet length! Dropping :%u bytes", pkt_len);
+      /* release GKI buffer */
+      GKI_freebuf(p_pkt);
+      return;
+    }
     /* First Segment of a packet */
     nfa_hci_cb.type = ((*p) >> 0x06) & 0x03;
     nfa_hci_cb.inst = (*p++ & 0x3F);
diff --git a/src/nfa/hci/nfa_hci_utils.cc b/src/nfa/hci/nfa_hci_utils.cc
index d64fe6c..1751af3 100644
--- a/src/nfa/hci/nfa_hci_utils.cc
+++ b/src/nfa/hci/nfa_hci_utils.cc
@@ -25,6 +25,7 @@
 
 #include <android-base/stringprintf.h>
 #include <base/logging.h>
+#include <log/log.h>
 
 #include "nfa_dm_int.h"
 #include "nfa_hci_api.h"
@@ -305,8 +306,13 @@
   bool first_pkt = true;
   uint16_t data_len;
   tNFA_STATUS status = NFA_STATUS_OK;
-  uint16_t max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
-
+  uint16_t max_seg_hcp_pkt_size;
+  if (nfa_hci_cb.buff_size > (NCI_DATA_HDR_SIZE + 2)) {
+    max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
+  } else {
+    android_errorWriteLog(0x534e4554, "124521372");
+    return NFA_STATUS_NO_BUFFERS;
+  }
   char buff[100];
 
   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
@@ -349,8 +355,12 @@
         memcpy(p_data, p_msg, data_len);
 
         p_buf->len += data_len;
-        msg_len -= data_len;
-        if (msg_len > 0) p_msg += data_len;
+        if (msg_len >= data_len) {
+          msg_len -= data_len;
+          p_msg += data_len;
+        } else {
+          msg_len = 0;
+        }
       }
 
       if (HCI_LOOPBACK_DEBUG == NFA_HCI_DEBUG_ON)
diff --git a/src/nfa/include/nfa_hci_int.h b/src/nfa/include/nfa_hci_int.h
index 5d13f95..456c279 100644
--- a/src/nfa/include/nfa_hci_int.h
+++ b/src/nfa/include/nfa_hci_int.h
@@ -371,6 +371,7 @@
   uint8_t active_host[NFA_HCI_MAX_HOST_IN_NETWORK];
   uint8_t reset_host[NFA_HCI_MAX_HOST_IN_NETWORK]; /* List of host reseting */
   bool b_low_power_mode;  /* Host controller in low power mode */
+  bool b_hci_new_sessionId; /* Command sent to set a new session Id */
   bool b_hci_netwk_reset; /* Command sent to reset HCI Network */
   bool w4_hci_netwk_init; /* Wait for other host in network to initialize */
   TIMER_LIST_ENT timer;   /* Timer to avoid indefinitely waiting for response */
diff --git a/src/nfc/ndef/ndef_utils.cc b/src/nfc/ndef/ndef_utils.cc
index 128cb69..6a95ebe 100644
--- a/src/nfc/ndef/ndef_utils.cc
+++ b/src/nfc/ndef/ndef_utils.cc
@@ -198,6 +198,10 @@
     }
 
     /* Check for OOB */
+    if (payload_len + type_len + id_len < payload_len ||
+        payload_len + type_len + id_len > msg_len) {
+      return (NDEF_MSG_LENGTH_MISMATCH);
+    }
     p_new = p_rec + (payload_len + type_len + id_len);
     if (p_rec > p_new || p_end < p_new) {
         android_errorWriteLog(0x534e4554, "126200054");
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index bc3d2e7..60cca32 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -370,16 +370,34 @@
 **
 *******************************************************************************/
 bool nfc_ncif_process_event(NFC_HDR* p_msg) {
-  uint8_t mt, pbf, gid, *p, *pp;
+  uint8_t mt, pbf, gid, *p;
   bool free = true;
   uint8_t oid;
+  uint16_t len;
   uint8_t *p_old, old_gid, old_oid, old_mt;
 
   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
 
-  pp = p;
-  NCI_MSG_PRS_HDR0(pp, mt, pbf, gid);
-  oid = ((*pp) & NCI_OID_MASK);
+  if (p_msg->len < 3) {
+    // Per NCI spec, every packets should have at least 3 bytes: HDR0, HDR1, and
+    // LEN field.
+    LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len: %d",
+                               p_msg->len);
+    return free;
+  }
+
+  // LEN field contains the size of the payload, not including the 3-byte packet
+  // header.
+  len = p[2] + 3;
+  if (p_msg->len < len) {
+    // Making sure the packet holds enough data than it claims.
+    LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len (%d) < len (%d)",
+                               p_msg->len, len);
+    return free;
+  }
+
+  NCI_MSG_PRS_HDR0(p, mt, pbf, gid);
+  oid = ((*p) & NCI_OID_MASK);
   if (nfc_cb.rawVsCbflag == true &&
       nfc_ncif_proc_proprietary_rsp(mt, gid, oid) == true) {
     nci_proc_prop_raw_vs_rsp(p_msg);
@@ -398,7 +416,7 @@
     case NCI_MT_RSP:
       DLOG_IF(INFO, nfc_debug_enabled)
           << StringPrintf("NFC received rsp gid:%d", gid);
-      oid = ((*pp) & NCI_OID_MASK);
+      oid = ((*p) & NCI_OID_MASK);
       p_old = nfc_cb.last_hdr;
       NCI_MSG_PRS_HDR0(p_old, old_mt, pbf, old_gid);
       old_oid = ((*p_old) & NCI_OID_MASK);
@@ -1546,6 +1564,10 @@
   uint8_t status;
   uint8_t num_responses;
 
+  if (plen < NFC_TL_SIZE) {
+    return;
+  }
+
   /* Pass result to RW_T3T for processing */
   STREAM_TO_UINT8(status, p);
   STREAM_TO_UINT8(num_responses, p);
diff --git a/src/nfc/tags/ce_t4t.cc b/src/nfc/tags/ce_t4t.cc
index 74c2463..19dfa96 100644
--- a/src/nfc/tags/ce_t4t.cc
+++ b/src/nfc/tags/ce_t4t.cc
@@ -646,6 +646,13 @@
     if (instruct == T4T_CMD_INS_SELECT) {
       /* P1 Byte is already parsed */
       if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) {
+        /* CLA+INS+P1+P2+Lc+FILE_ID = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE */
+        if (p_c_apdu->len < (T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE)) {
+          LOG(ERROR) << "Wrong length";
+          GKI_freebuf(p_c_apdu);
+          ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
+          return;
+        }
         ce_t4t_process_select_file_cmd(p_cmd);
       } else {
         LOG(ERROR) << StringPrintf("CET4T: Bad P1 byte (0x%02X)", select_type);
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index 0f38ab7..1483cdc 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -1942,6 +1942,9 @@
         block = (p_i93->rw_offset / p_i93->block_size);
         last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
 
+        if (length == 0) {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
         if ((*p) & I93_BLOCK_LOCKED) {
           if (block <= last_block) {
             p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
@@ -2616,7 +2619,7 @@
           (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
           ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
            (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
-        if ((*p) & I93_BLOCK_LOCKED) {
+        if (length == 0 || ((*p) & I93_BLOCK_LOCKED)) {
           rw_i93_handle_error(NFC_STATUS_FAILED);
           break;
         }
diff --git a/src/nfc/tags/rw_mfc.cc b/src/nfc/tags/rw_mfc.cc
index ef5bfdc..e78f3fc 100644
--- a/src/nfc/tags/rw_mfc.cc
+++ b/src/nfc/tags/rw_mfc.cc
@@ -405,10 +405,7 @@
 
     if (p_mfc->work_offset == p_mfc->ndef_length) {
       UINT8_TO_BE_STREAM(p, 0xFE);
-      index = index + 1;
-    }
-
-    if (p_mfc->work_offset > p_mfc->ndef_length) {
+    } else if (p_mfc->work_offset > p_mfc->ndef_length) {
       UINT8_TO_BE_STREAM(p, 0x00);
     } else {
       UINT8_TO_BE_STREAM(p, p_mfc->p_ndef_buffer[p_mfc->work_offset]);
@@ -1349,6 +1346,7 @@
   tRW_DETECT_NDEF_DATA ndef_data;
 
   DLOG_IF(INFO, nfc_debug_enabled) << __func__ << " State=" << p_mfc->state;
+  evt_data.status = NFC_STATUS_FAILED;
 
   /* Retry sending command if retry-count < max */
   if (rw_cb.cur_retry < RW_MAX_RETRIES) {
diff --git a/src/nfc/tags/rw_t3t.cc b/src/nfc/tags/rw_t3t.cc
index e0121de..d017ac3 100644
--- a/src/nfc/tags/rw_t3t.cc
+++ b/src/nfc/tags/rw_t3t.cc
@@ -1026,6 +1026,14 @@
 
       /* Add service code to T3T message */
       UINT16_TO_STREAM((*p), cur_service_code);
+
+      /* Validate num_services */
+      if (num_services >= T3T_MSG_SERVICE_LIST_MAX) {
+        LOG(ERROR) << StringPrintf(
+            "RW T3T: num_services (%i) reaches maximum (%i)", num_services,
+            T3T_MSG_SERVICE_LIST_MAX);
+        break;
+      }
     }
   }
 
diff --git a/src/nfc/tags/rw_t4t.cc b/src/nfc/tags/rw_t4t.cc
index 92ff5d9..b7b6144 100644
--- a/src/nfc/tags/rw_t4t.cc
+++ b/src/nfc/tags/rw_t4t.cc
@@ -2116,7 +2116,8 @@
     status = false;
     if (option == RW_T4T_CHK_EMPTY_I_BLOCK) {
       /* use empty I block for presence check */
-      p_data = (NFC_HDR*)GKI_getbuf(NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE);
+      p_data = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + NCI_MSG_OFFSET_SIZE +
+                                    NCI_DATA_HDR_SIZE);
       if (p_data != nullptr) {
         p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
         p_data->len = 0;