laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/42317?usp=email )
Change subject: ccid: Handle the TPDU-length = 4 case according to CCID spec ......................................................................
ccid: Handle the TPDU-length = 4 case according to CCID spec
While ISO7816-3 forbids any TPDU shorter from 5 bytes, the CCID spec begs to differ and actually permits a host to send us 4-byte TPDUs of Form 1, giving the responsibility of adding the P3=00h octet to the CCID implementation.
Let's implement this accordingly. While at it, also reject TPDUs of lengths 1, 2 and 3 bytes - just like zero-length TPDUs.
Change-Id: Ia27962bda526af3373b36d637e2b548aa01a3346 Closes: OS#6973 --- M ccid_common/ccid_device.c 1 file changed, 12 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/17/42317/1
diff --git a/ccid_common/ccid_device.c b/ccid_common/ccid_device.c index 8a53860..0ef85b6 100644 --- a/ccid_common/ccid_device.c +++ b/ccid_common/ccid_device.c @@ -457,17 +457,26 @@ /* Section 6.1.4 */ static int ccid_handle_xfr_block(struct ccid_slot *cs, struct msgb *msg) { - const union ccid_pc_to_rdr *u = msgb_ccid_out(msg); + union ccid_pc_to_rdr *u = msgb_ccid_out(msg); const struct ccid_header *ch = (const struct ccid_header *) u; struct msgb *resp; int rc;
- if (u->xfr_block.hdr.dwLength == 0) { + /* TODO: The checks below assume TPDU-level exchange and T=0. When adding + * APDU-level or character level exchange or T=1 support, this needs adjustment */ + if (u->xfr_block.hdr.dwLength < 4) { /* CCID Rev 1.1 permits a zero-length XfrBlock on the protocol level, but what should we do - * with a zero-length TPDU? We need to reject it as bError=1 (Bad dwLength) */ + * with a zero-length or otherwise short TPDU? We need to reject it as bError=1 (Bad dwLength) */ resp = ccid_gen_data_block(cs, u->xfr_block.hdr.bSeq, CCID_CMD_STATUS_FAILED, 1, 0, 0); goto out; + } else if (u->xfr_block.hdr.dwLength == 4) { + /* CCID v1.1 Section 3.2.1: + * Command TPDU = CLA INS P1 P2, the CCID is responsible to add P3=00h */ + msgb_put(msg, 1); + u->xfr_block.hdr.dwLength = 5; + u->xfr_block.abData[4] = 0x00; } + /* from 5 bytes upwards, we can simply transceive it */
/* handle this asynchronously */ rc = cs->ci->slot_ops->xfr_block_async(cs, msg, &u->xfr_block);