[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 3/8] usb-ccid: Set protocol parameters based
From: |
Marc-André Lureau |
Subject: |
Re: [Qemu-devel] [PATCH v2 3/8] usb-ccid: Set protocol parameters based on card ATR |
Date: |
Thu, 20 Jul 2017 09:35:02 +0000 |
On Thu, Jul 20, 2017 at 11:11 AM Stefan Fritsch <address@hidden> wrote:
> From: Stefan Fritsch <address@hidden>
>
> For the ATR interface bytes encoding see ISO/IEC 7816-3. For the
> interpretation of the protocol parameter block see the CCID
> specification.
>
> - Values that are not present in the ATR default to zero.
> - TA_1 is used to fill bmFindexDindex.
> - The high nibble of bmTCCKST0 must be the protocol (T=0 or T=1).
> - For T=0 the bWaitingInteger can be found in the global byte TC_2,
> for T=1 the waiting integer is in TB_3 and bIFSC is in TA_3.
>
> Signed-off-by: Stefan Fritsch <address@hidden>
> Signed-off-by: Christian Ehrhardt <address@hidden>
> ---
> hw/usb/dev-smartcard-reader.c | 66
> +++++++++++++++++++++++++++++++++++--------
> 1 file changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
> index 49791492ea..769949144b 100644
> --- a/hw/usb/dev-smartcard-reader.c
> +++ b/hw/usb/dev-smartcard-reader.c
> @@ -801,7 +801,7 @@ static void ccid_write_parameters(USBCCIDState *s,
> CCID_Header *recv)
> return;
> }
> h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
> - h->b.hdr.dwLength = 0;
> + h->b.hdr.dwLength = (s->bProtocolNum == 1) ? 7 : 5;
> h->b.hdr.bSlot = recv->bSlot;
> h->b.hdr.bSeq = recv->bSeq;
> h->b.bStatus = ccid_calc_status(s);
> @@ -871,6 +871,49 @@ static uint8_t atr_get_protocol_num(const uint8_t
> *atr, uint32_t len)
> return atr[i] & 0x0f;
> }
>
> +/*
> + * Get a specific interface byte TX_y (X='A'..'D' y=1..3)
> + * See ISO/IEC 7816-3:2006 Chapter 8 for details.
> + */
> +static uint8_t atr_get_TXY(const uint8_t *atr, uint32_t len, char x, int
> y)
> +{
> + int pos;
> + uint8_t t0, ti, i;
> +
> + if (x < 'A' || x > 'D') {
> + return 0;
> + }
>
or you could assert it, since it's compile time constant
(I have vague memories of parsing ATR, but the rest looks ok, it might be
worth to include tests for that function though)
> + x -= 'A';
> +
> + if (len < 2) {
> + return 0;
> + }
> + t0 = atr[1] >> 4;
> + pos = 2;
> + ti = 1;
> + /* Skip TA_i..TD_i if present while not at requested index y */
> + while (ti < y) {
> + pos += !!(t0 & 0x01) + !!(t0 & 0x02) + !!(t0 & 0x04);
> + if (pos >= len || !(t0 & 0x08)) {
> + return 0;
> + }
> + t0 = atr[pos++] >> 4;
> + ti++;
> + }
> + if (!(t0 & 0x01 << x)) {
> + return 0;
> + }
> + for (i = 0; i < x; ++i) {
> + if (t0 & (1 << i)) {
> + pos++;
> + }
> + }
> + if (pos >= len) {
> + return 0;
> + }
> + return atr[pos];
> +}
> +
> static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
> {
> const uint8_t *atr = NULL;
> @@ -890,21 +933,20 @@ static void ccid_write_data_block_atr(USBCCIDState
> *s, CCID_Header *recv)
> : s->bProtocolNum);
> switch (atr_protocol_num) {
> case 0:
> - /* TODO: unimplemented ATR T0 parameters */
> - t0->bmFindexDindex = 0;
> - t0->bmTCCKST0 = 0;
> + t0->bmFindexDindex = atr_get_TXY(atr, len, 'A', 1);
> + t0->bmTCCKST0 = 0; /* T0 */
> t0->bGuardTimeT0 = 0;
> - t0->bWaitingIntegerT0 = 0;
> + t0->bWaitingIntegerT0 = atr_get_TXY(atr, len, 'C', 2);
> t0->bClockStop = 0;
> break;
> case 1:
> - /* TODO: unimplemented ATR T1 parameters */
> - t1->bmFindexDindex = 0;
> - t1->bmTCCKST1 = 0;
> - t1->bGuardTimeT1 = 0;
> - t1->bWaitingIntegerT1 = 0;
> - t1->bClockStop = 0;
> - t1->bIFSC = 0;
> + /* NOTE: If present TD2 should specify protocl T=1 */
> + t1->bmFindexDindex = atr_get_TXY(atr, len, 'A', 1);
> + t1->bmTCCKST1 = 0x10; /* T1 */
> + t1->bGuardTimeT1 = atr_get_TXY(atr, len, 'C', 1);
> + t1->bWaitingIntegerT1 = atr_get_TXY(atr, len, 'B', 3);
> + t1->bClockStop = 0x00;
> + t1->bIFSC = atr_get_TXY(atr, len, 'A', 3);
> t1->bNadValue = 0;
> break;
> default:
> --
> 2.11.0
>
>
> --
Marc-André Lureau
- [Qemu-devel] [PATCH v2 0/8] usb-ccid: Misc fixes and T=1 support, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 2/8] usb-ccid: Fix USB packet generation for 64-Bytes sized packets., Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 7/8] usb-ccid: Increase ccid max APDU size, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 5/8] usb-ccid: Fix USB descriptor, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 3/8] usb-ccid: Set protocol parameters based on card ATR, Stefan Fritsch, 2017/07/20
- Re: [Qemu-devel] [PATCH v2 3/8] usb-ccid: Set protocol parameters based on card ATR,
Marc-André Lureau <=
- [Qemu-devel] [PATCH v2 8/8] usb-ccid: Reduce logging at level WARN, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 1/8] usb-ccid: Add support to dump all USB packets, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 6/8] usb-ccid: Fix chaining fields in CCID USB messages, Stefan Fritsch, 2017/07/20
- [Qemu-devel] [PATCH v2 4/8] usb-ccid: Fix ATR parsing, Stefan Fritsch, 2017/07/20