Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 485fdc9b authored by Mark A. Greer's avatar Mark A. Greer Committed by Samuel Ortiz
Browse files

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: default avatarThierry Escande <thierry.escande@linux.intel.com>
Tested-by: default avatarThierry Escande <thierry.escande@linux.intel.com>
Signed-off-by: default avatarMark A. Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 3e6b0de8
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -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:
		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;
		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:
		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)) {
	case DIGITAL_NFC_DEP_PFB_I_PDU:
		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;
	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");
		rc = -EINVAL;
		goto exit;
@@ -629,6 +652,9 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
		       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);

	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->curr_nfc_dep_pni = 0;

	rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
				 (void *)(unsigned long)rf_tech);
	if (rc)
@@ -800,6 +828,8 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,

	ddev->skb_add_crc(skb);

	ddev->curr_nfc_dep_pni = 0;

	rc = digital_tg_send_cmd(ddev, skb, 999,
				 digital_tg_send_atr_res_complete, NULL);
	if (rc)