pcsc-lite 2.5.3
atrhandler.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 1999-2002
5 * David Corcoran <corcoran@musclecard.com>
6 * Copyright (C) 2002-2023
7 * Ludovic Rousseau <ludovic.rousseau@free.fr>
8 *
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
152. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
183. The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
42
43#include "config.h"
44#include <string.h>
45
46#include "misc.h"
47#include "pcsclite.h"
48#include "debuglog.h"
49#include "atrhandler.h"
50
51/*
52 * Uncomment the following for ATR debugging
53 * or use ./configure --enable-debugatr
54 */
55/* #define ATR_DEBUG */
56
66short ATRDecodeAtr(int *availableProtocols, int *currentProtocol,
67 PUCHAR pucAtr, DWORD dwLength)
68{
69 USHORT p;
70 UCHAR Y1i, T; /* MSN/LSN of TDi */
71 int i = 1; /* value of the index in TAi, TBi, etc. */
72
73#ifdef ATR_DEBUG
74 if (dwLength > 0)
75 LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
76#endif
77
78 /*
79 * Zero out the bitmasks
80 */
81 *availableProtocols = SCARD_PROTOCOL_UNDEFINED;
82 *currentProtocol = SCARD_PROTOCOL_UNDEFINED;
83
84 if (dwLength < 2)
85 return -1;
86
87 /*
88 * Decode the TS byte
89 */
90 if ((pucAtr[0] != 0x3F) && (pucAtr[0] != 0x3B))
91 return -2;
92
93 /*
94 * Here comes the platform dependent stuff
95 */
96
97 /*
98 * Decode the T0 byte
99 */
100 Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */
101
102 p = 2;
103
104 /*
105 * Examine Y1
106 */
107 do
108 {
109 short TAi, TBi, TCi, TDi; /* Interface characters */
110
111#define READ_IF_PRESENT(mask, out) \
112 do { \
113 if (Y1i & (mask)) \
114 { \
115 if (p >= dwLength || p >= MAX_ATR_SIZE) \
116 return -5; \
117 (out) = pucAtr[p++]; \
118 } \
119 else \
120 (out) = -1; \
121 } while (0)
122
123 READ_IF_PRESENT(0x01, TAi);
124 READ_IF_PRESENT(0x02, TBi);
125 READ_IF_PRESENT(0x04, TCi);
126 READ_IF_PRESENT(0x08, TDi);
127
128 /* We don't use TBi and TCi but we must calculate them because
129 * of the p++ in the formulae */
130 (void)TBi;
131 (void)TCi;
132
133#ifdef ATR_DEBUG
134 Log9(PCSC_LOG_DEBUG,
135 "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
136 i, TAi, i, TBi, i, TCi, i, TDi);
137#endif
138
139 /*
140 * Examine TDi to determine protocol and more
141 */
142 if (TDi >= 0)
143 {
144 Y1i = TDi >> 4; /* Get the MSN in Y1 */
145 T = TDi & 0x0F; /* Get the LSN in K */
146
147 /*
148 * Set the current protocol TD1 (first TD only)
149 */
150 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
151 {
152 switch (T)
153 {
154 case 0:
155 *currentProtocol = SCARD_PROTOCOL_T0;
156 break;
157 case 1:
158 *currentProtocol = SCARD_PROTOCOL_T1;
159 break;
160 default:
161 return -3;
162 }
163 }
164
165#ifdef ATR_DEBUG
166 Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
167#endif
168 if (0 == T)
169 {
170 *availableProtocols |= SCARD_PROTOCOL_T0;
171 }
172 else
173 if (1 == T)
174 {
175 *availableProtocols |= SCARD_PROTOCOL_T1;
176 }
177 else
178 if (15 == T)
179 {
180 *availableProtocols |= SCARD_PROTOCOL_T15;
181 }
182 else
183 {
184 /*
185 * Do nothing for now since other protocols are not
186 * supported at this time
187 */
188 }
189 }
190 else
191 Y1i = 0;
192
193 /* test presence of TA2 */
194 if ((2 == i) && (TAi >= 0))
195 {
196 T = TAi & 0x0F;
197#ifdef ATR_DEBUG
198 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
199#endif
200 switch (T)
201 {
202 case 0:
203 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T0;
204 break;
205
206 case 1:
207 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T1;
208 break;
209
210 default:
211 return -4;
212 }
213 }
214
215 /* next interface characters index */
216 i++;
217 }
218 while (Y1i != 0);
219
220 /*
221 * If TDx is not set then the current must be T0
222 */
223 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
224 {
225 *currentProtocol = SCARD_PROTOCOL_T0;
226 *availableProtocols |= SCARD_PROTOCOL_T0;
227 }
228
229#ifdef ATR_DEBUG
230 Log3(PCSC_LOG_DEBUG, "CurrentProtocol: T=%d, AvailableProtocols: %d",
231 *currentProtocol - SCARD_PROTOCOL_T0, *availableProtocols);
232#endif
233
234 return 0;
235}
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
Definition atrhandler.c:66
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
This handles debugging.
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition pcsclite.h:240
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition pcsclite.h:243
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition pcsclite.h:242
#define SCARD_PROTOCOL_T15
T=15 protocol.
Definition pcsclite.h:245