NFC: digital: Enforce NFC-DEP PNI sequencing

NFC-DEP DEP_REQ and DEP_RES exchanges using 'I'
and 'ACK/NACK' PDUs have a sequence number called
the Packet Number Information (PNI).  The PNI
is incremented (modulo 4) after every DEP_REQ/
DEP_RES pair and should be verified by the digital
layer code.  That verification isn't always done,
though, so add code to make sure that it is done.

Reviewed-by: Thierry Escande <thierry.escande@linux.intel.com>
Tested-by: Thierry Escande <thierry.escande@linux.intel.com>
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Mark A. Greer 2014-09-23 16:38:07 -07:00 committed by Samuel Ortiz
parent 3e6b0de805
commit 485fdc9bb6

View File

@ -447,8 +447,18 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
pr_err("Received a ACK/NACK PDU\n"); pr_err("Received a ACK/NACK PDU\n");
if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
PROTOCOL_ERR("14.12.3.3");
rc = -EIO; rc = -EIO;
goto error; goto exit;
}
ddev->curr_nfc_dep_pni =
DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
rc = -EINVAL;
goto exit;
case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
@ -592,9 +602,22 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
case DIGITAL_NFC_DEP_PFB_I_PDU: case DIGITAL_NFC_DEP_PFB_I_PDU:
pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(pfb);
if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
PROTOCOL_ERR("14.12.3.4");
rc = -EIO;
goto exit;
}
rc = 0;
break; break;
case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
PROTOCOL_ERR("14.12.3.4");
rc = -EIO;
goto exit;
}
pr_err("Received a ACK/NACK PDU\n"); pr_err("Received a ACK/NACK PDU\n");
rc = -EINVAL; rc = -EINVAL;
goto exit; goto exit;
@ -629,6 +652,9 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
sizeof(ddev->did)); sizeof(ddev->did));
} }
ddev->curr_nfc_dep_pni =
DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
digital_skb_push_dep_sod(ddev, skb); digital_skb_push_dep_sod(ddev, skb);
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
@ -677,6 +703,8 @@ static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
ddev->curr_nfc_dep_pni = 0;
rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
(void *)(unsigned long)rf_tech); (void *)(unsigned long)rf_tech);
if (rc) if (rc)
@ -800,6 +828,8 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
ddev->curr_nfc_dep_pni = 0;
rc = digital_tg_send_cmd(ddev, skb, 999, rc = digital_tg_send_cmd(ddev, skb, 999,
digital_tg_send_atr_res_complete, NULL); digital_tg_send_atr_res_complete, NULL);
if (rc) if (rc)