xref: /illumos-gate/usr/src/common/ccid/atr.h (revision 6f1fa39e3cf1b335f342bbca41590e9d76ab29b7)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019, Joyent, Inc.
14  */
15 
16 #ifndef _ATR_H
17 #define	_ATR_H
18 
19 /*
20  * Parse Answer-To-Reset values. This header file is private to illumos and
21  * should not be shipped or used by applications.
22  *
23  * This is based on ISO/IEC 7816-3:2006. It has been designed such that if newer
24  * revisions come out that define reserved values, they will be ignored until
25  * this code is updated.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/usb/clients/ccid/ccid.h>
30 #ifndef	_KERNEL
31 #include <stdio.h>
32 #endif
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /*
39  * The ATR must have at least 2 bytes and then may have up to 33 bytes.
40  */
41 #define	ATR_LEN_MIN	2
42 #define	ATR_LEN_MAX	33
43 
44 typedef enum atr_parsecode {
45 	ATR_CODE_OK	= 0,
46 	ATR_CODE_TOO_SHORT,
47 	ATR_CODE_TOO_LONG,
48 	ATR_CODE_INVALID_TS,
49 	ATR_CODE_OVERRUN,
50 	ATR_CODE_UNDERRUN,
51 	ATR_CODE_CHECKSUM_ERROR,
52 	ATR_CODE_INVALID_TD1
53 } atr_parsecode_t;
54 
55 typedef enum atr_protocol {
56 	ATR_P_NONE	= 0,
57 	ATR_P_T0	= 1 << 0,
58 	ATR_P_T1	= 1 << 1
59 } atr_protocol_t;
60 
61 typedef enum atr_convention {
62 	ATR_CONVENTION_DIRECT	= 0x00,
63 	ATR_CONVENTION_INVERSE	= 0x01
64 } atr_convention_t;
65 
66 typedef enum atr_clock_stop {
67 	ATR_CLOCK_STOP_NONE	= 0x00,
68 	ATR_CLOCK_STOP_LOW	= 0x01,
69 	ATR_CLOCK_STOP_HI	= 0x02,
70 	ATR_CLOCK_STOP_BOTH	= 0x03
71 } atr_clock_stop_t;
72 
73 typedef enum atr_data_rate_choice {
74 	/*
75 	 * Indicates that the reader cannot support the data rate needed for the
76 	 * ICC.
77 	 */
78 	ATR_RATE_UNSUPPORTED	= 0x00,
79 	/*
80 	 * Indicates that the reader supports the ICC present, but must run at
81 	 * the protocol's default rate (Di index = Fi index = 1)
82 	 */
83 	ATR_RATE_USEDEFAULT	= 0x01,
84 	/*
85 	 * The reader supports the Di/Fi values that the ICC proposed in its ATR
86 	 * and no action beyond setting the parameters of the reader is required
87 	 * (this may be automatic depending on the reader's dwFeatures).
88 	 */
89 	ATR_RATE_USEATR		= 0x02,
90 	/*
91 	 * The reader can use the features of the ATR specified. However, it
92 	 * must change the data rate or frequency that the card is running at to
93 	 * proceed.
94 	 */
95 	ATR_RATE_USEATR_SETRATE	= 0x03
96 } atr_data_rate_choice_t;
97 
98 typedef enum atr_t1_checksum {
99 	ATR_T1_CHECKSUM_LRC	= 0x00,
100 	ATR_T1_CHECKSUM_CRC	= 0x01
101 } atr_t1_checksum_t;
102 
103 typedef struct atr_data atr_data_t;
104 
105 /*
106  * Allocate and free ATR data.
107  */
108 extern atr_data_t *atr_data_alloc(void);
109 extern void atr_data_free(atr_data_t *);
110 
111 /*
112  * Reset an allocated ATR data to be ready to parse something else.
113  */
114 extern void atr_data_reset(atr_data_t *);
115 
116 /*
117  * Parse the ATR data into an opaque structure that organizes the data and
118  * allows for various queries to be made on it later.
119  */
120 extern atr_parsecode_t atr_parse(const uint8_t *, size_t, atr_data_t *data);
121 extern const char *atr_strerror(atr_parsecode_t);
122 
123 /*
124  * Get an eumeration of supported protocols in this ATR data. Note that if a
125  * reserved protocol is encountered, we may not report it as we don't know of it
126  * at this time.
127  */
128 extern atr_protocol_t atr_supported_protocols(atr_data_t *);
129 
130 /*
131  * Based on the ATR determine what the default protocol is and whether or not it
132  * supports negotiation. When a ICC is not negotiable, it will always start up
133  * with a specific protocol and parameters based on the ATR and be ready to use.
134  * Otherwise, the card will be in a negotiable mode and be set to a default set
135  * of parameters.
136  */
137 extern boolean_t atr_params_negotiable(atr_data_t *);
138 extern atr_protocol_t atr_default_protocol(atr_data_t *);
139 
140 /*
141  * Protocol default values.
142  */
143 extern uint8_t atr_fi_default_index(void);
144 extern uint8_t atr_di_default_index(void);
145 
146 /*
147  * Obtain the table indexes that should be used by the device.
148  */
149 extern uint8_t atr_fi_index(atr_data_t *);
150 extern uint8_t atr_di_index(atr_data_t *);
151 extern atr_convention_t atr_convention(atr_data_t *);
152 extern uint8_t atr_extra_guardtime(atr_data_t *);
153 extern uint8_t atr_t0_wi(atr_data_t *);
154 extern atr_t1_checksum_t atr_t1_checksum(atr_data_t *);
155 extern uint8_t atr_t1_bwi(atr_data_t *);
156 extern uint8_t atr_t1_cwi(atr_data_t *);
157 extern atr_clock_stop_t atr_clock_stop(atr_data_t *);
158 extern uint8_t atr_t1_ifsc(atr_data_t *);
159 
160 /*
161  * Use this function to determine what set of Di and Fi values should be used by
162  * a reader, based on the parameters from the ATR and the reader's cclass.
163  */
164 extern atr_data_rate_choice_t atr_data_rate(atr_data_t *, ccid_class_descr_t *,
165     uint32_t *, uint_t, uint32_t *);
166 
167 #ifndef	_KERNEL
168 extern void atr_data_hexdump(const uint8_t *, size_t, FILE *);
169 extern void atr_data_dump(atr_data_t *, FILE *);
170 #endif
171 
172 /*
173  * String and table index values.
174  */
175 extern const char *atr_protocol_to_string(atr_protocol_t);
176 extern uint_t atr_fi_index_to_value(uint8_t);
177 extern const char *atr_fi_index_to_string(uint8_t);
178 extern const char *atr_fmax_index_to_string(uint8_t);
179 extern uint_t atr_di_index_to_value(uint8_t);
180 extern const char *atr_di_index_to_string(uint8_t);
181 extern const char *atr_clock_stop_to_string(atr_clock_stop_t);
182 extern const char *atr_convention_to_string(atr_convention_t);
183 
184 /*
185  * Functions for generating and testing PPS values. Before calling
186  * atr_pps_fidi_accepted(), one must call atr_pps_valid().
187  */
188 #define	PPS_BUFFER_MAX	6
189 extern uint_t atr_pps_generate(uint8_t *, size_t, atr_protocol_t, boolean_t,
190     uint8_t, uint8_t, boolean_t, uint8_t);
191 extern boolean_t atr_pps_valid(void *, size_t, void *, size_t);
192 extern boolean_t atr_pps_fidi_accepted(void *, size_t);
193 
194 #ifdef __cplusplus
195 }
196 #endif
197 
198 #endif /* _ATR_H */
199