blob: 1c6dd07add9b60a21f6c2791edcdd521a587d647 [file] [log] [blame]
Harald Welte63653742019-01-03 16:54:16 +01001#pragma once
Harald Weltea67be5f2020-09-03 10:04:36 +02002/* CCID Protocol related Definitions
3 *
4 * (C) 2019-2020 by Harald Welte <laforge@gnumonks.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19 */
20
Harald Welte63653742019-01-03 16:54:16 +010021#include <stdint.h>
Harald Welte4f25df62019-05-14 09:30:29 +020022#include <osmocom/core/utils.h>
Harald Welte63653742019-01-03 16:54:16 +010023
24/* Identifies the length of type of subordinate descriptors of a CCID device
25 * Table 5.1-1 Smart Card Device Class descriptors */
26struct usb_ccid_class_descriptor {
27 uint8_t bLength;
28 uint8_t bDescriptorType;
29 uint16_t bcdCCID;
30 uint8_t bMaxSlotIndex;
31 uint8_t bVoltageSupport;
32 uint32_t dwProtocols;
33 uint32_t dwDefaultClock;
34 uint32_t dwMaximumClock;
35 uint8_t bNumClockSupported;
36 uint32_t dwDataRate;
37 uint32_t dwMaxDataRate;
38 uint8_t bNumDataRatesSupported;
39 uint32_t dwMaxIFSD;
40 uint32_t dwSynchProtocols;
41 uint32_t dwMechanical;
42 uint32_t dwFeatures;
43 uint32_t dwMaxCCIDMessageLength;
44 uint8_t bClassGetResponse;
45 uint8_t bClassEnvelope;
46 uint16_t wLcdLayout;
47 uint8_t bPINSupport;
48 uint8_t bMaxCCIDBusySlots;
49} __attribute__((packed));
50/* handling of bulk out from host */
51
52enum ccid_msg_type {
53 /* Section 6.3 / Table 6.3-1: Interrupt IN */
54 RDR_to_PC_NotifySlotChange = 0x50,
55 RDR_to_PC_HardwareError = 0x51,
56
57 /* Section 6.1 / Table 6.1-1: Bulk OUT */
58 PC_to_RDR_IccPowerOn = 0x62,
59 PC_to_RDR_IccPowerOff = 0x63,
60 PC_to_RDR_GetSlotStatus = 0x65,
61 PC_to_RDR_XfrBlock = 0x6f,
62 PC_to_RDR_GetParameters = 0x6c,
63 PC_to_RDR_ResetParameters = 0x6d,
64 PC_to_RDR_SetParameters = 0x61,
65 PC_to_RDR_Escape = 0x6b,
66 PC_to_RDR_IccClock = 0x6e,
67 PC_to_RDR_T0APDU = 0x6a,
68 PC_to_RDR_Secure = 0x69,
69 PC_to_RDR_Mechanical = 0x71,
70 PC_to_RDR_Abort = 0x72,
71 PC_to_RDR_SetDataRateAndClockFrequency = 0x73,
72
73 /* Section 6.2 / Table 6.2-1: Bulk IN */
74 RDR_to_PC_DataBlock = 0x80,
75 RDR_to_PC_SlotStatus = 0x81,
76 RDR_to_PC_Parameters = 0x82,
77 RDR_to_PC_Escape = 0x83,
78 RDR_to_PC_DataRateAndClockFrequency = 0x84,
79};
80
81/* CCID message header on BULK-OUT endpoint */
82struct ccid_header {
83 uint8_t bMessageType;
84 uint32_t dwLength;
85 uint8_t bSlot;
86 uint8_t bSeq;
87} __attribute__ ((packed));
88
Harald Welteeb93f632019-05-11 20:08:09 +020089/* CCID Class-Specific Control Request (Section 5.3 / Table 5.3-1) */
90enum ccid_class_spec_req {
91 CLASS_SPEC_CCID_ABORT = 0x01,
92 CLASS_SPEC_CCID_GET_CLOCK_FREQ = 0x02,
93 CLASS_SPEC_CCID_GET_DATA_RATES = 0x03
94};
95
Harald Welte63653742019-01-03 16:54:16 +010096/***********************************************************************
97 * Bulk OUT
98 ***********************************************************************/
99
100/* Section 6.1.1 */
101enum ccid_power_select {
102 CCID_PWRSEL_AUTO = 0x00,
103 CCID_PWRSEL_5V0 = 0x01,
104 CCID_PWRSEL_3V0 = 0x02,
105 CCID_PWRSEL_1V8 = 0x03,
106};
107
108/* Section 6.1.1 */
109struct ccid_pc_to_rdr_icc_power_on {
110 struct ccid_header hdr;
111 uint8_t bPowerSelect;
112 uint8_t abRFU[2];
113} __attribute__ ((packed));
114/* Response: RDR_to_PC_DataBlock */
115
116/* Section 6.1.2 */
117struct ccid_pc_to_rdr_icc_power_off {
118 struct ccid_header hdr;
119 uint8_t abRFU[3];
120} __attribute__ ((packed));
121/* Response: RDR_to_PC_SlotStatus */
122
123/* Section 6.1.3 */
124struct ccid_pc_to_rdr_get_slot_status {
125 struct ccid_header hdr;
126 uint8_t abRFU[3];
127} __attribute__ ((packed));
128/* Response: RDR_to_PC_SlotStatus */
129
130/* Section 6.1.4 */
131struct ccid_pc_to_rdr_xfr_block {
132 struct ccid_header hdr;
133 uint8_t bBWI;
134 uint16_t wLevelParameter;
135 uint8_t abData[0];
136} __attribute__ ((packed));
137/* Response: RDR_to_PC_DataBlock */
138
139/* Section 6.1.5 */
140struct ccid_pc_to_rdr_get_parameters {
141 struct ccid_header hdr;
142 uint8_t abRFU[3];
143} __attribute__ ((packed));
144/* Response: RDR_to_PC_Parameters */
145
146/* Section 6.1.6 */
147struct ccid_pc_to_rdr_reset_parameters {
148 struct ccid_header hdr;
149 uint8_t abRFU[3];
150} __attribute__ ((packed));
151/* Response: RDR_to_PC_Parameters */
152
153/* Section 6.1.7 */
Harald Welte8579ce52019-05-15 12:22:24 +0200154enum ccid_protocol_num {
155 CCID_PROTOCOL_NUM_T0 = 0x00,
156 CCID_PROTOCOL_NUM_T1 = 0x01,
157 CCID_PROTOCOL_NUM_2WIRE = 0x80,
158 CCID_PROTOCOL_NUM_3WIRE = 0x81,
159 CCID_PROTOCOL_NUM_I2C = 0x82,
160};
161enum ccid_clock_stop {
162 CCID_CLOCK_STOP_NOTALLOWED = 0x00,
163 CCID_CLOCK_STOP_LOW = 0x01,
164 CCID_CLOCK_STOP_HIGH = 0x02,
165 CCID_CLOCK_STOP_EITHER = 0x03,
166};
167enum ccid_t1_csum_type {
168 CCID_CSUM_TYPE_LRC = 0,
169 CCID_CSUM_TYPE_CRC = 1,
170};
Harald Welte63653742019-01-03 16:54:16 +0100171struct ccid_proto_data_t0 {
172 uint8_t bmFindexDindex;
173 uint8_t bmTCCKST0;
174 uint8_t bGuardTimeT0;
175 uint8_t bWaitingIntegerT0;
176 uint8_t bClockStop;
177} __attribute__ ((packed));
178struct ccid_proto_data_t1 {
179 uint8_t bmFindexDindex;
180 uint8_t bmTCCKST1;
181 uint8_t bGuardTimeT1;
182 uint8_t bWaitingIntegersT1;
183 uint8_t bClockStop;
Harald Welte8579ce52019-05-15 12:22:24 +0200184 uint8_t bIFSC;
Harald Welte63653742019-01-03 16:54:16 +0100185 uint8_t bNadValue;
186} __attribute__ ((packed));
187struct ccid_pc_to_rdr_set_parameters {
188 struct ccid_header hdr;
189 uint8_t bProtocolNum;
190 uint8_t abRFU[2];
191 union {
192 struct ccid_proto_data_t0 t0;
193 struct ccid_proto_data_t1 t1;
194 } abProtocolData;
195} __attribute__ ((packed));
196/* Response: RDR_to_PC_Parameters */
197
198/* Section 6.1.8 */
199struct ccid_pc_to_rdr_escape {
200 struct ccid_header hdr;
201 uint8_t abRFU[3];
202 uint8_t abData[0];
203} __attribute__ ((packed));
204/* Response: RDR_to_PC_Escape */
205
206/* Section 6.1.9 */
207enum ccid_clock_command {
208 CCID_CLOCK_CMD_RESTART = 0x00,
209 CCID_CLOCK_CMD_STOP = 0x01,
210};
211struct ccid_pc_to_rdr_icc_clock {
212 struct ccid_header hdr;
213 uint8_t bClockCommand;
214 uint8_t abRFU[2];
215} __attribute__ ((packed));
216/* response: RDR_to_PC_SlotStatus */
217
218/* Section 6.1.10 */
219struct ccid_pc_to_rdr_t0apdu {
220 struct ccid_header hdr;
221 uint8_t bmChanges;
222 uint8_t bClassGetResponse;
223 uint8_t bClassEnvelope;
224} __attribute__ ((packed));
225/* Response: RDR_to_PC_SlotStatus */
226
227/* Section 6.1.11 */
228struct ccid_pc_to_rdr_secure {
229 struct ccid_header hdr;
230 uint8_t bBWI;
231 uint16_t wLevelParameter;
232 uint8_t abData[0];
233} __attribute__ ((packed));
234struct ccid_pin_operation_data {
235 uint8_t bPINOperation;
236 uint8_t abPNDataStructure[0];
237} __attribute__ ((packed));
238struct ccid_pin_verification_data {
239 uint8_t bTimeOut;
240 uint8_t bmFormatString;
241 uint8_t bmPINBlockString;
242 uint8_t bmPINLengthFormat;
243 uint16_t wPINMaxExtraDigit;
244 uint8_t bEntryValidationCondition;
245 uint8_t bNumberMessage;
246 uint16_t wLangId;
247 uint8_t bMsgIndex;
248 uint8_t bTecPrologue;
249 uint8_t abPINApdu[0];
250} __attribute__ ((packed));
251/* Response: RDR_to_PC_DataBlock */
252
253/* Section 6.1.12 */
254struct ccid_pc_to_rdr_mechanical {
255 struct ccid_header hdr;
256 uint8_t bFunction; /* ccid_mech_function */
257 uint8_t abRFU[2];
258} __attribute__ ((packed));
259enum ccid_mech_function {
260 CCID_MECH_FN_ACCEPT_CARD = 0x01,
261 CCID_MECH_FN_EJECT_CARD = 0x02,
262 CCID_MECH_FN_CAPTURE_CARD = 0x03,
263 CCID_MECH_FN_LOCK_CARD = 0x04,
264 CCID_MECH_FN_UNLOCK_CARD = 0x05,
265};
266/* Response: RDR_to_PC_SlotStatus */
267
268/* Section 6.1.13 */
269struct ccid_pc_to_rdr_abort {
270 struct ccid_header hdr;
271 uint8_t abRFU[3];
272} __attribute__ ((packed));
273/* Response: RDR_to_PC_SlotStatus */
274
275/* Section 6.1.14 */
276struct ccid_pc_to_rdr_set_rate_and_clock {
277 struct ccid_header hdr;
278 uint8_t abRFU[3];
279 uint32_t dwClockFrequency;
280 uint32_t dwDataRate;
281} __attribute__ ((packed));
282/* Response: RDR_to_PC_DataRateAndClockFrequency */
283
284union ccid_pc_to_rdr {
285 struct ccid_pc_to_rdr_icc_power_on icc_power_on;
286 struct ccid_pc_to_rdr_icc_power_off icc_power_off;
287 struct ccid_pc_to_rdr_get_slot_status get_slot_status;
288 struct ccid_pc_to_rdr_xfr_block xfr_block;
289 struct ccid_pc_to_rdr_get_parameters get_parameters;
290 struct ccid_pc_to_rdr_reset_parameters reset_parameters;
291 struct ccid_pc_to_rdr_set_parameters set_parameters;
292 struct ccid_pc_to_rdr_escape escape;
293 struct ccid_pc_to_rdr_icc_clock icc_clock;
294 struct ccid_pc_to_rdr_t0apdu t0apdu;
295 struct ccid_pc_to_rdr_secure secure;
296 struct ccid_pc_to_rdr_mechanical mechanical;
297 struct ccid_pc_to_rdr_abort abort;
298 struct ccid_pc_to_rdr_set_rate_and_clock set_rate_and_clock;
299};
300
301/***********************************************************************
302 * Bulk IN
303 ***********************************************************************/
304
305/* CCID message header on BULK-IN endpoint */
306struct ccid_header_in {
307 struct ccid_header hdr;
308 uint8_t bStatus;
309 uint8_t bError;
310} __attribute__ ((packed));
311
312/* Section 6.2.1 RDR_to_PC_DataBlock */
313struct ccid_rdr_to_pc_data_block {
314 struct ccid_header_in hdr;
315 uint8_t bChainParameter;
316 uint8_t abData[0];
317} __attribute__ ((packed));
318
319/* Section 6.2.2 RDR_to_PC_SlotStatus */
320struct ccid_rdr_to_pc_slot_status {
321 struct ccid_header_in hdr;
322 uint8_t bClockStatus;
323} __attribute__ ((packed));
324enum ccid_clock_status {
325 CCID_CLOCK_STATUS_RUNNING = 0x00,
326 CCID_CLOCK_STATUS_STOPPED_L = 0x01,
327 CCID_CLOCK_STATUS_STOPPED_H = 0x02,
328 CCID_CLOCK_STATUS_STOPPED_UNKN = 0x03,
329};
330
331/* Section 6.2.3 RDR_to_PC_Parameters */
332struct ccid_rdr_to_pc_parameters {
333 struct ccid_header_in hdr;
334 union {
335 struct ccid_proto_data_t0 t0;
336 struct ccid_proto_data_t1 t1;
337 } abProtocolData;
338} __attribute__ ((packed));
339
340/* Section 6.2.4 RDR_to_PC_Escape */
341struct ccid_rdr_to_pc_escape {
Harald Welte575531b2019-05-14 09:31:18 +0200342 struct ccid_header_in hdr;
Harald Welte63653742019-01-03 16:54:16 +0100343 uint8_t bRFU;
344 uint8_t abData[0];
345} __attribute__ ((packed));
346
347/* Section 6.2.5 RDR_to_PC_DataRateAndClockFrequency */
348struct ccid_rdr_to_pc_data_rate_and_clock {
Harald Welte575531b2019-05-14 09:31:18 +0200349 struct ccid_header_in hdr;
Harald Welte63653742019-01-03 16:54:16 +0100350 uint8_t bRFU;
351 uint32_t dwClockFrequency;
352 uint32_t dwDataRate;
353} __attribute__ ((packed));
354
355/* Section 6.2.6 */
356#define CCID_ICC_STATUS_MASK 0x03
357#define CCID_ICC_STATUS_PRES_ACT 0x00
358#define CCID_ICC_STATUS_PRES_INACT 0x01
359#define CCID_ICC_STATUS_NO_ICC 0x02
360#define CCID_CMD_STATUS_MASK 0xC0
361#define CCID_CMD_STATUS_OK 0x00
362#define CCID_CMD_STATUS_FAILED 0x40
363#define CCID_CMD_STATUS_TIME_EXT 0x80
364/* Table 6.2-2: Slot Error value when bmCommandStatus == 1 */
365enum ccid_error_code {
366 CCID_ERR_CMD_ABORTED = 0xff,
367 CCID_ERR_ICC_MUTE = 0xfe,
368 CCID_ERR_XFR_PARITY_ERROR = 0xfd,
369 CCID_ERR_XFR_OVERRUN = 0xfc,
370 CCID_ERR_HW_ERROR = 0xfb,
371 CCID_ERR_BAD_ATR_TS = 0xf8,
372 CCID_ERR_BAD_ATR_TCK = 0xf7,
373 CCID_ERR_ICC_PROTOCOL_NOT_SUPPORTED = 0xf6,
374 CCID_ERR_ICC_CLASS_NOT_SUPPORTED = 0xf5,
375 CCID_ERR_PROCEDURE_BYTE_CONFLICT = 0xf4,
376 CCID_ERR_DEACTIVATED_PROTOCOL = 0xf3,
377 CCID_ERR_BUSY_WITH_AUTO_SEQUENCE = 0xf2,
378 CCID_ERR_PIN_TIMEOUT = 0xf0,
379 CCID_ERR_PIN_CANCELLED = 0xef,
380 CCID_ERR_CMD_SLOT_BUSY = 0xe0,
381 CCID_ERR_CMD_NOT_SUPPORTED = 0x00
382};
383
384union ccid_rdr_to_pc {
385 struct ccid_rdr_to_pc_data_block data_block;
386 struct ccid_rdr_to_pc_slot_status slot_status;
387 struct ccid_rdr_to_pc_parameters parameters;
388 struct ccid_rdr_to_pc_escape escape;
389 struct ccid_rdr_to_pc_data_rate_and_clock rate_and_clock;
390};
391
392/***********************************************************************
393 * Interupt IN
394 ***********************************************************************/
395
396/* Section 6.3.1 */
397struct ccid_rdr_to_pc_notify_slot_change {
398 uint8_t bMessageType;
399 uint8_t bmSlotCCState[0]; /* as long as bNumSlots/4 padded to next byte */
400} __attribute__ ((packed));
401
402/* Section 6.3.1 */
403struct ccid_rdr_to_pc_hardware_error {
404 struct ccid_header hdr;
405 uint8_t bHardwareErrorCode;
406} __attribute__ ((packed));
407
408union ccid_rdr_to_pc_irq {
409 struct ccid_rdr_to_pc_notify_slot_change slot_change;
410 struct ccid_rdr_to_pc_hardware_error hw_error;
411};
Harald Welte4f25df62019-05-14 09:30:29 +0200412
413
414extern const struct value_string ccid_msg_type_vals[];
415extern const struct value_string ccid_class_spec_req_vals[];
416extern const struct value_string ccid_power_select_vals[];
417extern const struct value_string ccid_clock_command_vals[];
418extern const struct value_string ccid_error_code_vals[];
419