Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-usb-ccid.c
Line
Count
Source
1
/* packet-usb-ccid.c
2
 * Dissector for the Integrated Circuit Card Interface Device Class
3
 *
4
 * References:
5
 * https://www.usb.org/sites/default/files/DWG_Smart-Card_CCID_Rev110.pdf
6
 *
7
 * Copyright 2011, Tyson Key <tyson.key@gmail.com>
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 *
15
 */
16
#include "config.h"
17
18
#include <epan/decode_as.h>
19
#include <epan/packet.h>
20
#include <epan/prefs.h>
21
#include <epan/tfs.h>
22
#include <epan/unit_strings.h>
23
24
#include <wsutil/array.h>
25
#include "packet-usb.h"
26
27
static int proto_ccid;
28
29
static dissector_table_t subdissector_table;
30
31
static int hf_ccid_bMessageType;
32
static int hf_ccid_dwLength;
33
static int hf_ccid_bSlot;
34
static int hf_ccid_bSeq;
35
static int hf_ccid_bStatus;
36
static int hf_ccid_bStatus_bmIccStatus;
37
static int hf_ccid_bStatus_bmCommandStatus;
38
static int hf_ccid_bError;
39
static int hf_ccid_bRFU;
40
static int hf_ccid_abRFU;
41
static int hf_ccid_bChainParameter;
42
static int hf_ccid_bPowerSelect;
43
static int hf_ccid_bClockStatus;
44
static int hf_ccid_bProtocolNum;
45
static int hf_ccid_bBWI;
46
static int hf_ccid_wLevelParameter;
47
static int hf_ccid_bcdCCID;
48
static int hf_ccid_bMaxSlotIndex;
49
static int hf_ccid_bVoltageSupport;
50
static int hf_ccid_bVoltageSupport18;
51
static int hf_ccid_bVoltageSupport30;
52
static int hf_ccid_bVoltageSupport50;
53
static int hf_ccid_dwProtocols;
54
static int hf_ccid_dwProtocols_t0;
55
static int hf_ccid_dwProtocols_t1;
56
static int hf_ccid_dwDefaultClock;
57
static int hf_ccid_dwMaximumClock;
58
static int hf_ccid_bNumClockSupported;
59
static int hf_ccid_dwDataRate;
60
static int hf_ccid_dwMaxDataRate;
61
static int hf_ccid_bNumDataRatesSupported;
62
static int hf_ccid_dwMaxIFSD;
63
static int hf_ccid_dwSynchProtocols;
64
static int hf_ccid_dwMechanical;
65
static int hf_ccid_dwFeatures;
66
static int hf_ccid_dwFeatures_autoParam;
67
static int hf_ccid_dwFeatures_autoIccActivation;
68
static int hf_ccid_dwFeatures_autoIccVoltSelect;
69
static int hf_ccid_dwFeatures_autoIccClk;
70
static int hf_ccid_dwFeatures_autoBaudRate;
71
static int hf_ccid_dwFeatures_autoParamNegotiation;
72
static int hf_ccid_dwFeatures_autoPPS;
73
static int hf_ccid_dwFeatures_stopIccClk;
74
static int hf_ccid_dwFeatures_nadValNot0accept;
75
static int hf_ccid_dwFeatures_autoIfsd;
76
static int hf_ccid_dwFeatures_levelExchangeTDPU;
77
static int hf_ccid_dwFeatures_levelExchangeShortAPDU;
78
static int hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU;
79
static int hf_ccid_dwFeatures_UsbWakeUp;
80
static int hf_ccid_dwMaxCCIDMessageLength;
81
static int hf_ccid_bClassGetResponse;
82
static int hf_ccid_bClassEnvelope;
83
static int hf_ccid_wLcdLayout;
84
static int hf_ccid_wLcdLayout_lines;
85
static int hf_ccid_wLcdLayout_chars;
86
static int hf_ccid_bPINSupport;
87
static int hf_ccid_bPINSupport_modify;
88
static int hf_ccid_bPINSupport_vrfy;
89
static int hf_ccid_bMaxCCIDBusySlots;
90
static int hf_ccid_Reserved;
91
static int hf_ccid_bmSlotICCState;
92
static int hf_ccid_bmSlotICCState_slot0Current;
93
static int hf_ccid_bmSlotICCState_slot0Changed;
94
static int hf_ccid_bmSlotICCState_slot1Current;
95
static int hf_ccid_bmSlotICCState_slot1Changed;
96
static int hf_ccid_bmSlotICCState_slot2Current;
97
static int hf_ccid_bmSlotICCState_slot2Changed;
98
static int hf_ccid_bmSlotICCState_slot3Current;
99
static int hf_ccid_bmSlotICCState_slot3Changed;
100
static int hf_ccid_bmSlotICCState_slot4Current;
101
static int hf_ccid_bmSlotICCState_slot4Changed;
102
static int hf_ccid_bmSlotICCState_slot5Current;
103
static int hf_ccid_bmSlotICCState_slot5Changed;
104
static int hf_ccid_bmSlotICCState_slot6Current;
105
static int hf_ccid_bmSlotICCState_slot6Changed;
106
static int hf_ccid_bmSlotICCState_slot7Current;
107
static int hf_ccid_bmSlotICCState_slot7Changed;
108
static int hf_ccid_bHardwareErrorCode;
109
static int hf_ccid_bmFindexDindex;
110
static int hf_ccid_bmTCCKST0;
111
static int hf_ccid_bmTCCKST1;
112
static int hf_ccid_bGuardTimeT0;
113
static int hf_ccid_bGuardTimeT1;
114
static int hf_ccid_bWaitingIntegerT0;
115
static int hf_ccid_bmWaitingIntegersT1;
116
static int hf_ccid_bClockStop;
117
static int hf_ccid_bIFSC;
118
static int hf_ccid_bNadValue;
119
120
static dissector_handle_t usb_ccid_handle;
121
static dissector_handle_t usb_ccid_descr_handle;
122
123
124
static int * const bVoltageLevel_fields[] = {
125
    &hf_ccid_bVoltageSupport18,
126
    &hf_ccid_bVoltageSupport30,
127
    &hf_ccid_bVoltageSupport50,
128
    NULL
129
};
130
131
static int * const dwProtocols_fields[] = {
132
    &hf_ccid_dwProtocols_t0,
133
    &hf_ccid_dwProtocols_t1,
134
    NULL
135
};
136
137
static int * const bFeatures_fields[] = {
138
    /* XXX - add the missing components */
139
    &hf_ccid_dwFeatures_autoParam,
140
    &hf_ccid_dwFeatures_autoIccActivation,
141
    &hf_ccid_dwFeatures_autoIccVoltSelect,
142
    &hf_ccid_dwFeatures_autoIccClk,
143
    &hf_ccid_dwFeatures_autoBaudRate,
144
    &hf_ccid_dwFeatures_autoParamNegotiation,
145
    &hf_ccid_dwFeatures_autoPPS,
146
    &hf_ccid_dwFeatures_stopIccClk,
147
    &hf_ccid_dwFeatures_nadValNot0accept,
148
    &hf_ccid_dwFeatures_autoIfsd,
149
    &hf_ccid_dwFeatures_levelExchangeTDPU,
150
    &hf_ccid_dwFeatures_levelExchangeShortAPDU,
151
    &hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU,
152
    &hf_ccid_dwFeatures_UsbWakeUp,
153
    NULL
154
};
155
156
static int * const bPINSupport_fields[] = {
157
    &hf_ccid_bPINSupport_modify,
158
    &hf_ccid_bPINSupport_vrfy,
159
    NULL
160
};
161
162
static int * const bmSlotICCStateb0_fields[] = {
163
    &hf_ccid_bmSlotICCState_slot0Current,
164
    &hf_ccid_bmSlotICCState_slot0Changed,
165
    &hf_ccid_bmSlotICCState_slot1Current,
166
    &hf_ccid_bmSlotICCState_slot1Changed,
167
    &hf_ccid_bmSlotICCState_slot2Current,
168
    &hf_ccid_bmSlotICCState_slot2Changed,
169
    &hf_ccid_bmSlotICCState_slot3Current,
170
    &hf_ccid_bmSlotICCState_slot3Changed,
171
    NULL
172
};
173
174
static int * const bmSlotICCStateb1_fields[] = {
175
    &hf_ccid_bmSlotICCState_slot4Current,
176
    &hf_ccid_bmSlotICCState_slot4Changed,
177
    &hf_ccid_bmSlotICCState_slot5Current,
178
    &hf_ccid_bmSlotICCState_slot5Changed,
179
    &hf_ccid_bmSlotICCState_slot6Current,
180
    &hf_ccid_bmSlotICCState_slot6Changed,
181
    &hf_ccid_bmSlotICCState_slot7Current,
182
    &hf_ccid_bmSlotICCState_slot7Changed,
183
    NULL
184
};
185
186
static int * const bStatus_fields[] = {
187
    &hf_ccid_bStatus_bmIccStatus,
188
    &hf_ccid_bStatus_bmCommandStatus,
189
    NULL
190
};
191
192
/* smart card descriptor, as defined in section 5.1
193
   of the USB CCID specification */
194
0
#define USB_DESC_TYPE_SMARTCARD 0x21
195
196
/* Standardised Bulk Out message types */
197
0
#define PC_RDR_SET_PARAMS      0x61
198
0
#define PC_RDR_ICC_ON          0x62
199
0
#define PC_RDR_ICC_OFF         0x63
200
0
#define PC_RDR_GET_SLOT_STATUS 0x65
201
#define PC_RDR_SECURE          0x69
202
#define PC_RDR_T0APDU          0x6A
203
0
#define PC_RDR_ESCAPE          0x6B
204
0
#define PC_RDR_GET_PARAMS      0x6C
205
#define PC_RDR_RESET_PARAMS    0x6D
206
#define PC_RDR_ICC_CLOCK       0x6E
207
0
#define PC_RDR_XFR_BLOCK       0x6F
208
#define PC_RDR_MECH            0x71
209
#define PC_RDR_ABORT           0x72
210
#define PC_RDR_DATA_CLOCK      0x73
211
212
/* Standardised Bulk In message types */
213
0
#define RDR_PC_DATA_BLOCK      0x80
214
0
#define RDR_PC_SLOT_STATUS     0x81
215
0
#define RDR_PC_PARAMS          0x82
216
0
#define RDR_PC_ESCAPE          0x83
217
#define RDR_PC_DATA_CLOCK      0x84
218
219
/* Standardised Interrupt IN message types */
220
0
#define RDR_PC_NOTIF_SLOT_CHNG 0x50
221
0
#define RDR_PC_HWERROR         0x51
222
223
void proto_register_ccid(void);
224
void proto_reg_handoff_ccid(void);
225
226
static const value_string ccid_descriptor_type_vals[] = {
227
        {USB_DESC_TYPE_SMARTCARD, "smart card"},
228
        {0,NULL}
229
};
230
static value_string_ext ccid_descriptor_type_vals_ext =
231
    VALUE_STRING_EXT_INIT(ccid_descriptor_type_vals);
232
233
static const value_string ccid_opcode_vals[] = {
234
    /* Standardised Bulk Out message types */
235
    {PC_RDR_SET_PARAMS      , "PC_to_RDR_SetParameters"},
236
    {PC_RDR_ICC_ON          , "PC_to_RDR_IccPowerOn"},
237
    {PC_RDR_ICC_OFF         , "PC_to_RDR_IccPowerOff"},
238
    {PC_RDR_GET_SLOT_STATUS , "PC_to_RDR_GetSlotStatus"},
239
    {PC_RDR_SECURE          , "PC_to_RDR_Secure"},
240
    {PC_RDR_T0APDU          , "PC_to_RDR_T0APDU"},
241
    {PC_RDR_ESCAPE          , "PC_to_RDR_Escape"},
242
    {PC_RDR_GET_PARAMS      , "PC_to_RDR_GetParameters"},
243
    {PC_RDR_RESET_PARAMS    , "PC_to_RDR_ResetParameters"},
244
    {PC_RDR_ICC_CLOCK       , "PC_to_RDR_IccClock"},
245
    {PC_RDR_XFR_BLOCK       , "PC_to_RDR_XfrBlock"},
246
    {PC_RDR_MECH            , "PC_to_RDR_Mechanical"},
247
    {PC_RDR_ABORT           , "PC_to_RDR_Abort"},
248
    {PC_RDR_DATA_CLOCK      , "PC_to_RDR_SetDataRateAndClockFrequency"},
249
250
    /* Standardised Bulk In message types */
251
    {RDR_PC_DATA_BLOCK      , "RDR_to_PC_DataBlock"},
252
    {RDR_PC_SLOT_STATUS     , "RDR_to_PC_SlotStatus"},
253
    {RDR_PC_PARAMS          , "RDR_to_PC_Parameters"},
254
    {RDR_PC_ESCAPE          , "RDR_to_PC_Escape"},
255
    {RDR_PC_DATA_CLOCK      , "RDR_to_PC_DataRateAndClockFrequency"},
256
257
    /* Standardised Interrupt IN message types */
258
    {RDR_PC_NOTIF_SLOT_CHNG , "RDR_to_PC_NotifySlotChange"},
259
    {RDR_PC_HWERROR         , "RDR_to_PC_HardwareError"},
260
261
    /* End of message types */
262
    {0x00, NULL}
263
};
264
265
static const value_string ccid_messagetypes_vals[] = {
266
    /* Standardised Bulk Out message types */
267
    {PC_RDR_SET_PARAMS      , "PC to Reader: Set Parameters"},
268
    {PC_RDR_ICC_ON          , "PC to Reader: ICC Power On"},
269
    {PC_RDR_ICC_OFF         , "PC to Reader: ICC Power Off"},
270
    {PC_RDR_GET_SLOT_STATUS , "PC to Reader: Get Slot Status"},
271
    {PC_RDR_SECURE          , "PC to Reader: Secure"},
272
    {PC_RDR_T0APDU          , "PC to Reader: T=0 APDU"},
273
    {PC_RDR_ESCAPE          , "PC to Reader: Escape"},
274
    {PC_RDR_GET_PARAMS      , "PC to Reader: Get Parameters"},
275
    {PC_RDR_RESET_PARAMS    , "PC to Reader: Reset Parameters"},
276
    {PC_RDR_ICC_CLOCK       , "PC to Reader: ICC Clock"},
277
    {PC_RDR_XFR_BLOCK       , "PC to Reader: Transfer Block"},
278
    {PC_RDR_MECH            , "PC to Reader: Mechanical"},
279
    {PC_RDR_ABORT           , "PC to Reader: Abort"},
280
    {PC_RDR_DATA_CLOCK      , "PC to Reader: Set Data Rate and Clock Frequency"},
281
282
    /* Standardised Bulk In message types */
283
    {RDR_PC_DATA_BLOCK      , "Reader to PC: Data Block"},
284
    {RDR_PC_SLOT_STATUS     , "Reader to PC: Slot Status"},
285
    {RDR_PC_PARAMS          , "Reader to PC: Parameters"},
286
    {RDR_PC_ESCAPE          , "Reader to PC: Escape"},
287
    {RDR_PC_DATA_CLOCK      , "Reader to PC: Data Rate and Clock Frequency"},
288
289
    /* Standardised Interrupt IN message types */
290
    {RDR_PC_NOTIF_SLOT_CHNG , "Reader to PC: Notify Slot Change"},
291
    {RDR_PC_HWERROR         , "Reader to PC: Hardware Error"},
292
293
    /* End of message types */
294
    {0x00, NULL}
295
};
296
297
static const value_string ccid_voltage_levels_vals[] = {
298
    /* Standardised voltage levels */
299
    {0x00, "Automatic Voltage Selection"},
300
    {0x01, "5.0 volts"},
301
    {0x02, "3.0 volts"},
302
    {0x03, "1.8 volts"},
303
304
    /* End of voltage levels */
305
    {0x00, NULL}
306
};
307
308
static const value_string ccid_clock_states_vals[] = {
309
    /* Standardised clock states */
310
    {0x00, "Clock running"},
311
    {0x01, "Clock stopped in state L"},
312
    {0x02, "Clock stopped in state H"},
313
    {0x03, "Clock stopped in an unknown state"},
314
315
    /* End of clock states */
316
    {0x00, NULL}
317
};
318
319
static const value_string ccid_proto_structs_vals[] = {
320
    /* Standardised clock states */
321
    {0x00, "Structure for protocol T=0"},
322
    {0x01, "Structure for protocol T=1"},
323
324
    /* Marked as RFU, but added for completeness: */
325
    {0x80, "Structure for 2-wire protocol"},
326
    {0x81, "Structure for 3-wire protocol"},
327
    {0x82, "Structure for I2C protocol"},
328
329
    /* End of protocol structures */
330
    {0x00, NULL}
331
};
332
333
static const value_string ccid_status_icc_status_vals[] = {
334
    /* Standardised icc status */
335
    { 0x00, "An ICC is present and active" },
336
    { 0x01, "An ICC is present and inactive" },
337
    { 0x02, "No ICC is present" },
338
    { 0x03, "RFU" },
339
340
    /* End of icc status */
341
    { 0x00, NULL }
342
};
343
344
static const value_string ccid_status_cmd_status_vals[] = {
345
    /* Standardised status values */
346
    { 0x00, "Processed without error " },
347
    { 0x01, "Failed" },
348
    { 0x02, "Time Extension is requested " },
349
    { 0x03, "RFU" },
350
351
    /* End of status values */
352
    { 0x00, NULL }
353
};
354
355
/* Subtree handles: set by register_subtree_array */
356
static int ett_ccid;
357
static int ett_ccid_desc;
358
static int ett_ccid_protocol_data_structure;
359
static int ett_ccid_voltage_level;
360
static int ett_ccid_protocols;
361
static int ett_ccid_features;
362
static int ett_ccid_lcd_layout;
363
static int ett_ccid_pin_support;
364
static int ett_ccid_slot_change;
365
static int ett_ccid_status;
366
367
static int
368
dissect_usb_ccid_descriptor(tvbuff_t *tvb, packet_info *pinfo _U_,
369
        proto_tree *tree, void *data _U_)
370
0
{
371
0
    int         offset = 0;
372
0
    uint8_t     descriptor_type;
373
0
    uint8_t     descriptor_len;
374
0
    proto_item *freq_item;
375
0
    proto_tree *desc_tree;
376
0
    uint8_t     num_clock_supp;
377
0
    proto_item *lcd_layout_item;
378
0
    proto_tree *lcd_layout_tree;
379
380
0
    descriptor_len  = tvb_get_uint8(tvb, offset);
381
0
    descriptor_type = tvb_get_uint8(tvb, offset+1);
382
0
    if (descriptor_type!=USB_DESC_TYPE_SMARTCARD)
383
0
        return 0;
384
385
0
    desc_tree = proto_tree_add_subtree(tree, tvb, offset, descriptor_len,
386
0
                ett_ccid_desc, NULL, "SMART CARD DEVICE CLASS DESCRIPTOR");
387
388
0
    dissect_usb_descriptor_header(desc_tree, tvb, offset,
389
0
            &ccid_descriptor_type_vals_ext);
390
0
    offset += 2;
391
392
0
    proto_tree_add_item(desc_tree, hf_ccid_bcdCCID, tvb,
393
0
            offset, 2, ENC_LITTLE_ENDIAN);
394
0
    offset += 2;
395
396
0
    proto_tree_add_item(desc_tree, hf_ccid_bMaxSlotIndex, tvb,
397
0
            offset, 1, ENC_LITTLE_ENDIAN);
398
0
    offset++;
399
0
    proto_tree_add_bitmask(desc_tree, tvb, offset,
400
0
            hf_ccid_bVoltageSupport, ett_ccid_voltage_level, bVoltageLevel_fields,
401
0
            ENC_LITTLE_ENDIAN);
402
0
    offset++;
403
404
0
    proto_tree_add_bitmask(desc_tree, tvb, offset,
405
0
            hf_ccid_dwProtocols, ett_ccid_protocols, dwProtocols_fields,
406
0
            ENC_LITTLE_ENDIAN);
407
0
    offset += 4;
408
409
0
    proto_tree_add_item(desc_tree, hf_ccid_dwDefaultClock, tvb,
410
0
            offset, 4, ENC_LITTLE_ENDIAN);
411
0
    offset += 4;
412
0
    proto_tree_add_item(desc_tree, hf_ccid_dwMaximumClock, tvb,
413
0
            offset, 4, ENC_LITTLE_ENDIAN);
414
0
    offset += 4;
415
0
    num_clock_supp = tvb_get_uint8(tvb, offset);
416
0
    freq_item = proto_tree_add_item(desc_tree, hf_ccid_bNumClockSupported, tvb,
417
0
            offset, 1, ENC_LITTLE_ENDIAN);
418
0
    if (num_clock_supp==0)
419
0
        proto_item_append_text(freq_item, " (only default and maximum)");
420
0
    offset++;
421
422
0
    proto_tree_add_item(desc_tree, hf_ccid_dwDataRate,
423
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
424
0
    offset += 4;
425
0
    proto_tree_add_item(desc_tree, hf_ccid_dwMaxDataRate,
426
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
427
0
    offset += 4;
428
0
    proto_tree_add_item(desc_tree, hf_ccid_bNumDataRatesSupported,
429
0
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
430
0
    offset++;
431
432
0
    proto_tree_add_item(desc_tree, hf_ccid_dwMaxIFSD,
433
0
        tvb, offset, 4, ENC_LITTLE_ENDIAN);
434
0
    offset += 4;
435
436
0
    proto_tree_add_item(desc_tree, hf_ccid_dwSynchProtocols,
437
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
438
0
    offset += 4;
439
440
0
    proto_tree_add_item(desc_tree, hf_ccid_dwMechanical,
441
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
442
0
    offset += 4;
443
444
0
    proto_tree_add_bitmask(desc_tree, tvb, offset,
445
0
            hf_ccid_dwFeatures, ett_ccid_features, bFeatures_fields,
446
0
            ENC_LITTLE_ENDIAN);
447
0
    offset += 4;
448
449
0
    proto_tree_add_item(desc_tree, hf_ccid_dwMaxCCIDMessageLength,
450
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
451
0
    offset += 4;
452
453
0
    proto_tree_add_item(desc_tree, hf_ccid_bClassGetResponse,
454
0
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
455
0
    offset++;
456
0
    proto_tree_add_item(desc_tree, hf_ccid_bClassEnvelope,
457
0
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
458
0
    offset++;
459
460
0
    lcd_layout_item = proto_tree_add_item(desc_tree, hf_ccid_wLcdLayout,
461
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
462
0
    lcd_layout_tree = proto_item_add_subtree(
463
0
            lcd_layout_item, ett_ccid_lcd_layout);
464
0
    proto_tree_add_item(lcd_layout_tree, hf_ccid_wLcdLayout_lines,
465
0
            tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
466
0
    proto_tree_add_item(lcd_layout_tree, hf_ccid_wLcdLayout_chars,
467
0
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
468
0
    offset += 2;
469
470
0
    proto_tree_add_bitmask(desc_tree, tvb, offset,
471
0
            hf_ccid_bPINSupport, ett_ccid_pin_support, bPINSupport_fields,
472
0
            ENC_LITTLE_ENDIAN);
473
0
    offset++;
474
475
0
    proto_tree_add_item(desc_tree, hf_ccid_bMaxCCIDBusySlots,
476
0
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
477
0
    offset++;
478
479
0
    return offset;
480
0
}
481
482
483
static int
484
dissect_ccid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
485
0
{
486
0
    proto_item *item;
487
0
    proto_tree *ccid_tree;
488
0
    uint8_t     cmd;
489
0
    uint32_t    payload_len;
490
0
    tvbuff_t   *next_tvb;
491
0
    urb_info_t *urb;
492
0
    int len_remaining;
493
0
    uint8_t bProtocolNum;
494
0
    proto_tree *protocol_tree;
495
496
    /* Reject the packet if data is NULL */
497
0
    if (data == NULL)
498
0
        return 0;
499
0
    urb = (urb_info_t *)data;
500
501
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCCID");
502
0
    col_set_str(pinfo->cinfo, COL_INFO,     "CCID Packet");
503
504
    /* Start with a top-level item to add everything else to */
505
0
    item = proto_tree_add_item(tree, proto_ccid, tvb, 0, 10, ENC_NA);
506
0
    ccid_tree = proto_item_add_subtree(item, ett_ccid);
507
508
0
    proto_tree_add_item(ccid_tree, hf_ccid_bMessageType, tvb, 0, 1, ENC_LITTLE_ENDIAN);
509
0
    cmd = tvb_get_uint8(tvb, 0);
510
511
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(cmd, ccid_messagetypes_vals, "Unknown"));
512
513
0
    switch (cmd) {
514
515
0
    case PC_RDR_SET_PARAMS:
516
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
517
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
518
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
519
0
        proto_tree_add_item(ccid_tree, hf_ccid_bProtocolNum, tvb, 7, 1, ENC_LITTLE_ENDIAN);
520
521
        /* Placeholder for abRFU */
522
0
        proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 8, 2, ENC_LITTLE_ENDIAN);
523
524
0
        payload_len = tvb_get_letohl(tvb, 1);
525
526
        /* abProtocolDataStructure */
527
0
        bProtocolNum = tvb_get_uint8(tvb, 7);
528
0
        switch (bProtocolNum)
529
0
        {
530
0
            case 0: /* T=0 */
531
0
                protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=0");
532
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
533
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST0, tvb, 11, 1, ENC_LITTLE_ENDIAN);
534
0
                proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT0, tvb, 12, 1, ENC_LITTLE_ENDIAN);
535
0
                proto_tree_add_item(protocol_tree, hf_ccid_bWaitingIntegerT0, tvb, 13, 1, ENC_LITTLE_ENDIAN);
536
0
                proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
537
0
                break;
538
539
0
            case 1: /* T=1 */
540
0
                protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=1");
541
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
542
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST1, tvb, 11, 1, ENC_LITTLE_ENDIAN);
543
0
                proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT1, tvb, 12, 1, ENC_LITTLE_ENDIAN);
544
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmWaitingIntegersT1, tvb, 13, 1, ENC_LITTLE_ENDIAN);
545
0
                proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
546
0
                proto_tree_add_item(protocol_tree, hf_ccid_bIFSC, tvb, 15, 1, ENC_LITTLE_ENDIAN);
547
0
                proto_tree_add_item(protocol_tree, hf_ccid_bNadValue, tvb, 16, 1, ENC_LITTLE_ENDIAN);
548
0
                break;
549
550
0
            default:
551
0
                next_tvb = tvb_new_subset_remaining(tvb, 10);
552
0
                call_data_dissector(next_tvb, pinfo, tree);
553
0
        }
554
0
        break;
555
556
0
    case PC_RDR_ICC_ON:
557
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
558
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
559
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
560
0
        proto_tree_add_item(ccid_tree, hf_ccid_bPowerSelect, tvb, 7, 1, ENC_LITTLE_ENDIAN);
561
562
        /* Placeholder for abRFU */
563
0
        proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 8, 2, ENC_LITTLE_ENDIAN);
564
0
        break;
565
566
0
    case PC_RDR_ICC_OFF:
567
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
568
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
569
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
570
571
        /* Placeholder for abRFU */
572
0
        proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
573
0
        break;
574
575
0
    case PC_RDR_GET_SLOT_STATUS:
576
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
577
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
578
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
579
580
        /* Placeholder for abRFU */
581
0
        proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
582
0
        break;
583
584
0
    case PC_RDR_GET_PARAMS:
585
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
586
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
587
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
588
589
        /* Placeholder for abRFU */
590
0
        proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
591
0
        break;
592
593
0
    case PC_RDR_XFR_BLOCK:
594
0
    case PC_RDR_ESCAPE:
595
0
        proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength,
596
0
                tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
597
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
598
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
599
600
0
        if (cmd == PC_RDR_ESCAPE) {
601
0
            proto_tree_add_item(ccid_tree, hf_ccid_abRFU, tvb, 7, 3, ENC_NA);
602
0
        } else {
603
0
            proto_tree_add_item(ccid_tree, hf_ccid_bBWI, tvb, 7, 1, ENC_LITTLE_ENDIAN);
604
0
            proto_tree_add_item(ccid_tree, hf_ccid_wLevelParameter, tvb, 8, 2, ENC_LITTLE_ENDIAN);
605
0
        }
606
607
0
        if (payload_len == 0)
608
0
            break;
609
610
0
        next_tvb = tvb_new_subset_length(tvb, 10, payload_len);
611
        /* sent/received is from the perspective of the card reader */
612
0
        pinfo->p2p_dir = P2P_DIR_SENT;
613
614
0
        if (!dissector_try_payload_with_data(subdissector_table, next_tvb, pinfo, tree, true, urb)) {
615
0
            call_data_dissector(next_tvb, pinfo, tree);
616
0
        }
617
0
        break;
618
619
0
    case RDR_PC_DATA_BLOCK:
620
0
    case RDR_PC_ESCAPE:
621
0
        proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength,
622
0
                tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
623
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
624
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
625
0
        proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
626
0
        proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
627
0
        if (cmd == RDR_PC_ESCAPE)
628
0
            proto_tree_add_item(ccid_tree, hf_ccid_bRFU, tvb, 9, 1, ENC_LITTLE_ENDIAN);
629
0
        else
630
0
            proto_tree_add_item(ccid_tree, hf_ccid_bChainParameter, tvb, 9, 1, ENC_LITTLE_ENDIAN);
631
632
0
        if (payload_len == 0)
633
0
            break;
634
635
0
        next_tvb = tvb_new_subset_length(tvb, 10, payload_len);
636
0
        pinfo->p2p_dir = P2P_DIR_RECV;
637
638
0
        if (!dissector_try_payload_with_data(subdissector_table, next_tvb, pinfo, tree, true, urb)) {
639
0
            call_data_dissector(next_tvb, pinfo, tree);
640
0
        }
641
0
        break;
642
643
0
    case RDR_PC_SLOT_STATUS:
644
0
        proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
645
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
646
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
647
0
        proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
648
0
        proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
649
0
        proto_tree_add_item(ccid_tree, hf_ccid_bClockStatus, tvb, 9, 1, ENC_LITTLE_ENDIAN);
650
0
        break;
651
652
0
    case RDR_PC_PARAMS:
653
0
        proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
654
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
655
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
656
0
        proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
657
0
        proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
658
0
        proto_tree_add_item_ret_uint8(ccid_tree, hf_ccid_bProtocolNum, tvb, 9, 1, ENC_LITTLE_ENDIAN, &bProtocolNum);
659
660
        /* abProtocolDataStructure */
661
0
        switch (bProtocolNum)
662
0
        {
663
0
            case 0: /* T=0 */
664
0
                if (payload_len > 0) {
665
0
                    protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=0");
666
0
                    proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
667
0
                    proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST0, tvb, 11, 1, ENC_LITTLE_ENDIAN);
668
0
                    proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT0, tvb, 12, 1, ENC_LITTLE_ENDIAN);
669
0
                    proto_tree_add_item(protocol_tree, hf_ccid_bWaitingIntegerT0, tvb, 13, 1, ENC_LITTLE_ENDIAN);
670
0
                    proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
671
0
                }
672
0
                break;
673
674
0
            case 1: /* T=1 */
675
0
                protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=1");
676
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
677
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST1, tvb, 11, 1, ENC_LITTLE_ENDIAN);
678
0
                proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT1, tvb, 12, 1, ENC_LITTLE_ENDIAN);
679
0
                proto_tree_add_item(protocol_tree, hf_ccid_bmWaitingIntegersT1, tvb, 13, 1, ENC_LITTLE_ENDIAN);
680
0
                proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
681
0
                proto_tree_add_item(protocol_tree, hf_ccid_bIFSC, tvb, 15, 1, ENC_LITTLE_ENDIAN);
682
0
                proto_tree_add_item(protocol_tree, hf_ccid_bNadValue, tvb, 16, 1, ENC_LITTLE_ENDIAN);
683
0
                break;
684
685
0
            default:
686
0
                next_tvb = tvb_new_subset_remaining(tvb, 10);
687
0
                call_data_dissector(next_tvb, pinfo, tree);
688
0
        }
689
0
        break;
690
691
    /*Interrupt IN*/
692
0
    case RDR_PC_NOTIF_SLOT_CHNG:
693
0
        proto_tree_add_bitmask(ccid_tree, tvb, 1,
694
0
            hf_ccid_bmSlotICCState, ett_ccid_slot_change, bmSlotICCStateb0_fields,
695
0
            ENC_LITTLE_ENDIAN);
696
0
        len_remaining = tvb_reported_length_remaining (tvb, 2);
697
0
        if (len_remaining <= 0)
698
0
            break;
699
0
        proto_tree_add_bitmask(ccid_tree, tvb, 2,
700
0
            hf_ccid_bmSlotICCState, ett_ccid_slot_change, bmSlotICCStateb1_fields,
701
0
            ENC_LITTLE_ENDIAN);
702
0
        break;
703
704
0
    case RDR_PC_HWERROR:
705
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 1, 1, ENC_LITTLE_ENDIAN);
706
0
        proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 2, 1, ENC_LITTLE_ENDIAN);
707
0
        proto_tree_add_item(ccid_tree, hf_ccid_bHardwareErrorCode, tvb, 3, 1, ENC_LITTLE_ENDIAN);
708
0
        break;
709
710
711
712
0
    }
713
714
    /* TODO: Try use "offset" instead of hardcoded constants */
715
0
    return tvb_captured_length(tvb);
716
0
}
717
718
void
719
proto_register_ccid(void)
720
14
{
721
14
    static hf_register_info hf[] = {
722
723
14
        {&hf_ccid_bMessageType,
724
14
         { "Message Type", "usbccid.bMessageType", FT_UINT8, BASE_HEX,
725
14
           VALS(ccid_opcode_vals), 0x0, NULL, HFILL }},
726
14
        {&hf_ccid_dwLength,
727
14
         { "Packet Length", "usbccid.dwLength", FT_UINT32, BASE_DEC,
728
14
           NULL, 0x0, NULL, HFILL }},
729
14
        {&hf_ccid_bSlot,
730
14
         { "Slot", "usbccid.bSlot", FT_UINT8, BASE_DEC,
731
14
           NULL, 0x0, NULL, HFILL }},
732
14
        {&hf_ccid_bSeq,
733
14
         { "Sequence", "usbccid.bSeq", FT_UINT8, BASE_DEC,
734
14
           NULL, 0x0, NULL, HFILL }},
735
14
        {&hf_ccid_bStatus,
736
14
         { "Status", "usbccid.bStatus", FT_UINT8, BASE_DEC,
737
14
           NULL, 0x0, NULL, HFILL }},
738
14
        {&hf_ccid_bStatus_bmIccStatus,
739
14
         { "Status", "usbccid.bStatus.bmIccStatus", FT_UINT8, BASE_DEC,
740
14
           VALS(ccid_status_icc_status_vals), 0x03, NULL, HFILL }},
741
14
        {&hf_ccid_bStatus_bmCommandStatus,
742
14
         { "Status", "usbccid.bStatus.bmCommandStatus", FT_UINT8, BASE_DEC,
743
14
           VALS(ccid_status_cmd_status_vals), 0xC0, NULL, HFILL }},
744
14
        {&hf_ccid_bError,
745
14
         { "Error", "usbccid.bError", FT_UINT8, BASE_DEC,
746
14
           NULL, 0x0, NULL, HFILL }},
747
14
        {&hf_ccid_bRFU,
748
14
         { "RFU", "usbccid.bRFU", FT_UINT8, BASE_HEX,
749
14
           NULL, 0x0, NULL, HFILL }},
750
14
        {&hf_ccid_abRFU,
751
14
         { "RFU", "usbccid.abRFU", FT_BYTES, BASE_NONE,
752
14
           NULL, 0x0, NULL, HFILL }},
753
14
        {&hf_ccid_bChainParameter,
754
14
         { "Chain Parameter", "usbccid.bChainParameter", FT_UINT8, BASE_DEC,
755
14
           NULL, 0x0, NULL, HFILL }},
756
14
        {&hf_ccid_bPowerSelect,
757
14
         { "Voltage Level", "usbccid.bPowerSelect", FT_UINT8, BASE_HEX,
758
14
           VALS(ccid_voltage_levels_vals), 0x0, NULL, HFILL }},
759
14
        {&hf_ccid_bClockStatus,
760
14
         { "Clock Status", "usbccid.bClockStatus", FT_UINT8, BASE_HEX,
761
14
           VALS(ccid_clock_states_vals), 0x0, NULL, HFILL }},
762
14
        {&hf_ccid_bProtocolNum,
763
14
         { "Data Structure Type", "usbccid.bProtocolNum", FT_UINT8, BASE_HEX,
764
14
           VALS(ccid_proto_structs_vals), 0x0, NULL, HFILL }},
765
14
        {&hf_ccid_bBWI,
766
14
         { "Block Wait Time Integer", "usbccid.bBWI", FT_UINT8, BASE_HEX,
767
14
           NULL, 0x0, NULL, HFILL }},
768
14
        {&hf_ccid_wLevelParameter,
769
14
         { "Level Parameter", "usbccid.wLevelParameter", FT_UINT16, BASE_HEX,
770
14
           NULL, 0x0, NULL, HFILL }},
771
14
        {&hf_ccid_bcdCCID,
772
14
         { "bcdCCID", "usbccid.bcdCCID", FT_UINT16, BASE_HEX,
773
14
           NULL, 0x0, NULL, HFILL }},
774
14
        {&hf_ccid_bMaxSlotIndex,
775
14
         { "max slot index", "usbccid.bMaxSlotIndex", FT_UINT8, BASE_HEX,
776
14
           NULL, 0x0, NULL, HFILL }},
777
14
        {&hf_ccid_bVoltageSupport,
778
14
         { "voltage support", "usbccid.bVoltageSupport", FT_UINT8, BASE_HEX,
779
14
           NULL, 0x0, NULL, HFILL }},
780
14
        {&hf_ccid_bVoltageSupport18,
781
14
         { "1.8V", "usbccid.bVoltageSupport.18", FT_BOOLEAN, 8,
782
14
            TFS(&tfs_supported_not_supported), 0x04, NULL, HFILL }},
783
14
        {&hf_ccid_bVoltageSupport30,
784
14
         { "3.0V", "usbccid.bVoltageSupport.30", FT_BOOLEAN, 8,
785
14
            TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
786
14
        {&hf_ccid_bVoltageSupport50,
787
14
         { "5.0V", "usbccid.bVoltageSupport.50", FT_BOOLEAN, 8,
788
14
            TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
789
14
        {&hf_ccid_dwProtocols,
790
14
         { "dwProtocols", "usbccid.dwProtocols", FT_UINT32, BASE_HEX,
791
14
           NULL, 0x0, NULL, HFILL }},
792
14
        {&hf_ccid_dwProtocols_t0,
793
14
         { "T=0", "usbccid.dwProtocols.t0", FT_BOOLEAN, 32,
794
14
            TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
795
14
        {&hf_ccid_dwProtocols_t1,
796
14
         { "T=1", "usbccid.dwProtocols.t1", FT_BOOLEAN, 32,
797
14
            TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
798
14
        {&hf_ccid_dwDefaultClock,
799
14
         { "default clock frequency", "usbccid.dwDefaultClock",
800
14
             FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_khz), 0x0, NULL, HFILL }},
801
14
        {&hf_ccid_dwMaximumClock,
802
14
         { "maximum clock frequency", "usbccid.dwMaximumClock",
803
14
             FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_khz), 0x0, NULL, HFILL }},
804
14
        {&hf_ccid_bNumClockSupported,
805
14
         { "number of supported clock frequencies", "usbccid.bNumClockSupported",
806
14
             FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
807
14
        {&hf_ccid_dwDataRate,
808
14
         { "default ICC I/O data rate in bps", "usbccid.dwDataRate",
809
14
             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
810
14
        {&hf_ccid_dwMaxDataRate,
811
14
         { "maximum ICC I/O data rate in bps", "usbccid.dwMaxDataRate",
812
14
             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
813
14
        {&hf_ccid_bNumDataRatesSupported,
814
14
         { "number of supported data rates", "usbccid.bNumDataRatesSupported",
815
14
             FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
816
14
        { &hf_ccid_dwMaxIFSD,
817
14
         { "maximum IFSD supported", "usbccid.dwMaxIFSD",
818
14
             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
819
14
        {&hf_ccid_dwSynchProtocols,
820
14
         { "supported protocol types", "usbccid.dwSynchProtocols",
821
14
             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
822
14
        {&hf_ccid_dwMechanical,
823
14
         { "mechanical characteristics", "usbccid.dwMechanical",
824
14
             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
825
14
        {&hf_ccid_dwFeatures,
826
14
         { "intelligent features", "usbccid.dwFeatures",
827
14
             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
828
14
        {&hf_ccid_dwFeatures_autoIccActivation,
829
14
         { "Automatic activation of ICC on inserting",
830
14
             "usbccid.dwFeatures.autoIccActivation", FT_BOOLEAN, 32,
831
14
             TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
832
14
        {&hf_ccid_dwFeatures_autoIccVoltSelect,
833
14
         { "Automatic ICC voltage selection",
834
14
             "usbccid.dwFeatures.autoIccVoltSelect", FT_BOOLEAN, 32,
835
14
             TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
836
14
        {&hf_ccid_dwFeatures_autoParam,
837
14
         { "Automatic parameter configuration based on ATR",
838
14
             "usbccid.dwFeatures.autoParam", FT_BOOLEAN, 32,
839
14
             TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
840
14
        {&hf_ccid_dwFeatures_autoIccClk,
841
14
         { "Automatic ICC clock frequency change",
842
14
             "usbccid.dwFeatures.autoIccClk", FT_BOOLEAN, 32,
843
14
             TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
844
14
        {&hf_ccid_dwFeatures_autoBaudRate,
845
14
         { "Automatic baud rate change",
846
14
             "usbccid.dwFeatures.autoBaudRate", FT_BOOLEAN, 32,
847
14
             TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
848
14
        {&hf_ccid_dwFeatures_autoParamNegotiation,
849
14
         { "Automatic parameters negotiation",
850
14
             "usbccid.dwFeatures.autoParamNegotiation", FT_BOOLEAN, 32,
851
14
             TFS(&tfs_supported_not_supported), 0x00000040, NULL, HFILL }},
852
14
        {&hf_ccid_dwFeatures_autoPPS,
853
14
         { "Automatic PPS",
854
14
             "usbccid.dwFeatures.autoPPS", FT_BOOLEAN, 32,
855
14
             TFS(&tfs_supported_not_supported), 0x00000080, NULL, HFILL }},
856
14
        {&hf_ccid_dwFeatures_stopIccClk,
857
14
         { "CCID can set ICC in clock stop mode",
858
14
             "usbccid.dwFeatures.stopIccClk", FT_BOOLEAN, 32,
859
14
             TFS(&tfs_supported_not_supported), 0x00000100, NULL, HFILL }},
860
14
        {&hf_ccid_dwFeatures_nadValNot0accept,
861
14
         { "NAD value other than 00 accepted",
862
14
             "usbccid.dwFeatures.nadValNot0accept", FT_BOOLEAN, 32,
863
14
             TFS(&tfs_supported_not_supported), 0x00000200, NULL, HFILL }},
864
14
        {&hf_ccid_dwFeatures_autoIfsd,
865
14
         { "Automatic IFSD exchange as first exchange",
866
14
             "usbccid.dwFeatures.autoIfsd", FT_BOOLEAN, 32,
867
14
             TFS(&tfs_supported_not_supported), 0x00000400, NULL, HFILL }},
868
14
        {&hf_ccid_dwFeatures_levelExchangeTDPU,
869
14
         { "TPDU level exchanges",
870
14
             "usbccid.dwFeatures.levelExchangeTDPU", FT_BOOLEAN, 32,
871
14
             TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
872
14
        {&hf_ccid_dwFeatures_levelExchangeShortAPDU,
873
14
         { "Short APDU level exchange",
874
14
             "usbccid.dwFeatures.levelExchangeShortAPDU", FT_BOOLEAN, 32,
875
14
             TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
876
14
        {&hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU,
877
14
         { "Short and Extended APDU level exchange",
878
14
             "usbccid.dwFeatures.levelExchangeShortExtendedAPDU", FT_BOOLEAN, 32,
879
14
             TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
880
14
        {&hf_ccid_dwFeatures_UsbWakeUp,
881
14
         { "USB Wake up signaling supported on card insertion and removal",
882
14
             "usbccid.dwFeatures.UsbWakeUp", FT_BOOLEAN, 32,
883
14
             TFS(&tfs_supported_not_supported), 0x00100000, NULL, HFILL }},
884
14
        {&hf_ccid_dwMaxCCIDMessageLength,
885
14
         { "maximum CCID message length", "usbccid.dwMaxCCIDMessageLength",
886
14
             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
887
14
        {&hf_ccid_bClassGetResponse,
888
14
         { "default class for Get Response", "usbccid.hf_ccid_bClassGetResponse",
889
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
890
14
        {&hf_ccid_bClassEnvelope,
891
14
         { "default class for Envelope", "usbccid.hf_ccid_bClassEnvelope",
892
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
893
14
        {&hf_ccid_wLcdLayout,
894
14
         { "LCD layout", "usbccid.hf_ccid_wLcdLayout",
895
14
             FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
896
14
        {&hf_ccid_wLcdLayout_lines,
897
14
         { "Lines", "usbccid.hf_ccid_wLcdLayout.lines",
898
14
             FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
899
14
        {&hf_ccid_wLcdLayout_chars,
900
14
         { "Characters per line", "usbccid.hf_ccid_wLcdLayout.chars",
901
14
             FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
902
14
        {&hf_ccid_bPINSupport,
903
14
         { "PIN support", "usbccid.hf_ccid_bPINSupport",
904
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
905
14
        {&hf_ccid_bPINSupport_modify,
906
14
         { "PIN modification", "usbccid.hf_ccid_bPINSupport.modify",
907
14
             FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
908
14
        {&hf_ccid_bPINSupport_vrfy,
909
14
         { "PIN verification", "usbccid.hf_ccid_bPINSupport.verify",
910
14
             FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
911
14
        {&hf_ccid_bMaxCCIDBusySlots,
912
14
         { "maximum number of busy slots", "usbccid.hf_ccid_bMaxCCIDBusySlots",
913
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
914
14
        {&hf_ccid_Reserved,
915
14
         { "Reserved for Future Use", "usbccid.hf_ccid_Reserved",
916
14
             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
917
14
        { &hf_ccid_bmSlotICCState,
918
14
         { "Slot ICC State", "usbccid.hf_ccid_bmSlotICCState",
919
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
920
14
        { &hf_ccid_bmSlotICCState_slot0Current,
921
14
         { "Slot 0 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot0Current",
922
14
             FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, NULL, HFILL } },
923
14
        { &hf_ccid_bmSlotICCState_slot0Changed,
924
14
         { "Slot 0 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot0Changed",
925
14
             FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
926
14
        { &hf_ccid_bmSlotICCState_slot1Current,
927
14
         { "Slot 1 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot1Current",
928
14
             FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, NULL, HFILL } },
929
14
        { &hf_ccid_bmSlotICCState_slot1Changed,
930
14
         { "Slot 1 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot1Changed",
931
14
             FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08, NULL, HFILL } },
932
14
        { &hf_ccid_bmSlotICCState_slot2Current,
933
14
         { "Slot 2 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot2Current",
934
14
             FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, NULL, HFILL } },
935
14
        { &hf_ccid_bmSlotICCState_slot2Changed,
936
14
         { "Slot 2 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot2Changed",
937
14
             FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL, HFILL } },
938
14
        { &hf_ccid_bmSlotICCState_slot3Current,
939
14
         { "Slot 3 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot3Current",
940
14
             FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x40, NULL, HFILL } },
941
14
        { &hf_ccid_bmSlotICCState_slot3Changed,
942
14
         { "Slot 3 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot3Changed",
943
14
             FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, NULL, HFILL } },
944
14
        { &hf_ccid_bmSlotICCState_slot4Current,
945
14
         { "Slot 4 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot4Current",
946
14
          FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, NULL, HFILL } },
947
14
        { &hf_ccid_bmSlotICCState_slot4Changed,
948
14
         { "Slot 4 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot4Changed",
949
14
          FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
950
14
        { &hf_ccid_bmSlotICCState_slot5Current,
951
14
         { "Slot 5 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot5Current",
952
14
          FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, NULL, HFILL } },
953
14
        { &hf_ccid_bmSlotICCState_slot5Changed,
954
14
         { "Slot 5 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot5Changed",
955
14
          FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08, NULL, HFILL } },
956
14
        { &hf_ccid_bmSlotICCState_slot6Current,
957
14
         { "Slot 6 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot6Current",
958
14
          FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, NULL, HFILL } },
959
14
        { &hf_ccid_bmSlotICCState_slot6Changed,
960
14
         { "Slot 6 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot6Changed",
961
14
          FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL, HFILL } },
962
14
        { &hf_ccid_bmSlotICCState_slot7Current,
963
14
         { "Slot 7 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot7Current",
964
14
          FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x40, NULL, HFILL } },
965
14
        { &hf_ccid_bmSlotICCState_slot7Changed,
966
14
         { "Slot 7 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot7Changed",
967
14
          FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, NULL, HFILL } },
968
14
        { &hf_ccid_bHardwareErrorCode,
969
14
         { "Hardware Error Code", "usbccid.hf_ccid_bHardwareErrorCode",
970
14
             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
971
14
        {&hf_ccid_bmFindexDindex,
972
14
         { "Fi/Di selecting clock rate", "usbccid.bmFindexDindex", FT_UINT8, BASE_HEX,
973
14
           NULL, 0x0, NULL, HFILL }},
974
14
        {&hf_ccid_bmTCCKST0,
975
14
         { "Convention used", "usbccid.bmTCCKST0", FT_UINT8, BASE_HEX,
976
14
           NULL, 0x0, NULL, HFILL }},
977
14
        {&hf_ccid_bmTCCKST1,
978
14
         { "Checksum type - Convention used", "usbccid.bmTCCKST1", FT_UINT8, BASE_HEX,
979
14
           NULL, 0x0, NULL, HFILL }},
980
14
        {&hf_ccid_bGuardTimeT0,
981
14
         { "Extra Guardtime between two characters", "usbccid.bGuardTimeT0", FT_UINT8, BASE_HEX,
982
14
           NULL, 0x0, NULL, HFILL }},
983
14
        {&hf_ccid_bGuardTimeT1,
984
14
         { "Extra Guardtime", "usbccid.bGuardTimeT1", FT_UINT8, BASE_HEX,
985
14
           NULL, 0x0, NULL, HFILL }},
986
14
        {&hf_ccid_bmWaitingIntegersT1,
987
14
         { "BWI - CWI", "usbccid.bmWaitingIntegersT1", FT_UINT8, BASE_HEX,
988
14
           NULL, 0x0, NULL, HFILL }},
989
14
        {&hf_ccid_bClockStop,
990
14
         { "ICC Clock Stop Support", "usbccid.bClockStop", FT_UINT8, BASE_HEX,
991
14
           NULL, 0x0, NULL, HFILL }},
992
14
        {&hf_ccid_bIFSC,
993
14
         { "Size of negotiated IFSC", "usbccid.bIFSC", FT_UINT8, BASE_HEX,
994
14
           NULL, 0x0, NULL, HFILL }},
995
14
        {&hf_ccid_bNadValue,
996
14
         { "NAD", "usbccid.bNadValue", FT_UINT8, BASE_HEX,
997
14
           NULL, 0x0, NULL, HFILL }},
998
14
        {&hf_ccid_bWaitingIntegerT0,
999
14
         { "WI for T= 0 used to define WWT", "usbccid.bWaitingIntegerT0", FT_UINT8, BASE_HEX,
1000
14
           NULL, 0x0, NULL, HFILL }},
1001
14
    };
1002
1003
14
    static int *ett[] = {
1004
14
        &ett_ccid,
1005
14
        &ett_ccid_desc,
1006
14
        &ett_ccid_protocol_data_structure,
1007
14
        &ett_ccid_voltage_level,
1008
14
        &ett_ccid_protocols,
1009
14
        &ett_ccid_features,
1010
14
        &ett_ccid_lcd_layout,
1011
14
        &ett_ccid_pin_support,
1012
14
        &ett_ccid_slot_change,
1013
14
        &ett_ccid_status
1014
14
    };
1015
1016
14
    module_t *pref_mod;
1017
1018
14
    proto_ccid = proto_register_protocol("USB CCID", "USBCCID", "usbccid");
1019
14
    proto_register_field_array(proto_ccid, hf, array_length(hf));
1020
14
    proto_register_subtree_array(ett, array_length(ett));
1021
1022
14
    pref_mod = prefs_register_protocol_obsolete(proto_ccid);
1023
14
    prefs_register_obsolete_preference(pref_mod, "prtype");
1024
1025
14
    usb_ccid_handle = register_dissector("usbccid", dissect_ccid, proto_ccid);
1026
14
    usb_ccid_descr_handle = register_dissector("usbccid.descriptor", dissect_usb_ccid_descriptor, proto_ccid);
1027
1028
14
    subdissector_table = register_decode_as_next_proto(proto_ccid, "usbccid.subdissector", "USB CCID payload", NULL);
1029
14
}
1030
1031
/* Handler registration */
1032
void
1033
proto_reg_handoff_ccid(void)
1034
14
{
1035
14
    dissector_add_uint("usb.descriptor", IF_CLASS_SMART_CARD, usb_ccid_descr_handle);
1036
1037
14
    dissector_add_uint("usb.bulk", IF_CLASS_SMART_CARD, usb_ccid_handle);
1038
1039
14
    dissector_add_for_decode_as("usb.device", usb_ccid_handle);
1040
14
    dissector_add_for_decode_as("usb.product", usb_ccid_handle);
1041
14
    dissector_add_for_decode_as("usb.protocol", usb_ccid_handle);
1042
14
}
1043
1044
/*
1045
* Editor modelines - https://www.wireshark.org/tools/modelines.html
1046
*
1047
* Local variables:
1048
* c-basic-offset: 4
1049
* tab-width: 8
1050
* indent-tabs-mode: nil
1051
* End:
1052
*
1053
* ex: set shiftwidth=4 tabstop=8 expandtab:
1054
* :indentSize=4:tabSize=8:noTabs=true:
1055
*/