diff options
| author | Mark A. Greer <mgreer@animalcreek.com> | 2014-09-23 19:38:07 -0400 |
|---|---|---|
| committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-11-28 06:38:47 -0500 |
| commit | 485fdc9bb6f81d68aa30b399b9bc33cf27d65ba4 (patch) | |
| tree | 0c57a081a707ef1768dab3fe9094707e263cd32f | |
| parent | 3e6b0de8053ae724931799f1b5d4f009b9fc4b44 (diff) | |
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>
| -rw-r--r-- | net/nfc/digital_dep.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index d5e669b0dedf..95a69898d5f5 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c | |||
| @@ -447,8 +447,18 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | |||
| 447 | 447 | ||
| 448 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | 448 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: |
| 449 | pr_err("Received a ACK/NACK PDU\n"); | 449 | pr_err("Received a ACK/NACK PDU\n"); |
| 450 | rc = -EIO; | 450 | |
| 451 | goto error; | 451 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { |
| 452 | PROTOCOL_ERR("14.12.3.3"); | ||
| 453 | rc = -EIO; | ||
| 454 | goto exit; | ||
| 455 | } | ||
| 456 | |||
| 457 | ddev->curr_nfc_dep_pni = | ||
| 458 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | ||
| 459 | |||
| 460 | rc = -EINVAL; | ||
| 461 | goto exit; | ||
| 452 | 462 | ||
| 453 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | 463 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: |
| 454 | if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { | 464 | 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, | |||
| 592 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { | 602 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { |
| 593 | case DIGITAL_NFC_DEP_PFB_I_PDU: | 603 | case DIGITAL_NFC_DEP_PFB_I_PDU: |
| 594 | pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); | 604 | pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); |
| 595 | ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(pfb); | 605 | |
| 606 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | ||
| 607 | PROTOCOL_ERR("14.12.3.4"); | ||
| 608 | rc = -EIO; | ||
| 609 | goto exit; | ||
| 610 | } | ||
| 611 | |||
| 612 | rc = 0; | ||
| 596 | break; | 613 | break; |
| 597 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | 614 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: |
| 615 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | ||
| 616 | PROTOCOL_ERR("14.12.3.4"); | ||
| 617 | rc = -EIO; | ||
| 618 | goto exit; | ||
| 619 | } | ||
| 620 | |||
| 598 | pr_err("Received a ACK/NACK PDU\n"); | 621 | pr_err("Received a ACK/NACK PDU\n"); |
| 599 | rc = -EINVAL; | 622 | rc = -EINVAL; |
| 600 | goto exit; | 623 | goto exit; |
| @@ -629,6 +652,9 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) | |||
| 629 | sizeof(ddev->did)); | 652 | sizeof(ddev->did)); |
| 630 | } | 653 | } |
| 631 | 654 | ||
| 655 | ddev->curr_nfc_dep_pni = | ||
| 656 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | ||
| 657 | |||
| 632 | digital_skb_push_dep_sod(ddev, skb); | 658 | digital_skb_push_dep_sod(ddev, skb); |
| 633 | 659 | ||
| 634 | ddev->skb_add_crc(skb); | 660 | ddev->skb_add_crc(skb); |
| @@ -677,6 +703,8 @@ static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did, | |||
| 677 | 703 | ||
| 678 | ddev->skb_add_crc(skb); | 704 | ddev->skb_add_crc(skb); |
| 679 | 705 | ||
| 706 | ddev->curr_nfc_dep_pni = 0; | ||
| 707 | |||
| 680 | rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, | 708 | rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, |
| 681 | (void *)(unsigned long)rf_tech); | 709 | (void *)(unsigned long)rf_tech); |
| 682 | if (rc) | 710 | if (rc) |
| @@ -800,6 +828,8 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | |||
| 800 | 828 | ||
| 801 | ddev->skb_add_crc(skb); | 829 | ddev->skb_add_crc(skb); |
| 802 | 830 | ||
| 831 | ddev->curr_nfc_dep_pni = 0; | ||
| 832 | |||
| 803 | rc = digital_tg_send_cmd(ddev, skb, 999, | 833 | rc = digital_tg_send_cmd(ddev, skb, 999, |
| 804 | digital_tg_send_atr_res_complete, NULL); | 834 | digital_tg_send_atr_res_complete, NULL); |
| 805 | if (rc) | 835 | if (rc) |
