pcsc-lite 2.5.2
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 (p >= dwLength || p >= MAX_ATR_SIZE) \
114 return -5; \
115 (out) = (Y1i & (mask)) ? pucAtr[p++] : -1; \
116 } while (0)
117
118 READ_IF_PRESENT(0x01, TAi);
119 READ_IF_PRESENT(0x02, TBi);
120 READ_IF_PRESENT(0x04, TCi);
121 READ_IF_PRESENT(0x08, TDi);
122
123 /* We don't use TBi and TCi but we must calculate them because
124 * of the p++ in the formulae */
125 (void)TBi;
126 (void)TCi;
127
128#ifdef ATR_DEBUG
129 Log9(PCSC_LOG_DEBUG,
130 "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
131 i, TAi, i, TBi, i, TCi, i, TDi);
132#endif
133
134 /*
135 * Examine TDi to determine protocol and more
136 */
137 if (TDi >= 0)
138 {
139 Y1i = TDi >> 4; /* Get the MSN in Y1 */
140 T = TDi & 0x0F; /* Get the LSN in K */
141
142 /*
143 * Set the current protocol TD1 (first TD only)
144 */
145 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
146 {
147 switch (T)
148 {
149 case 0:
150 *currentProtocol = SCARD_PROTOCOL_T0;
151 break;
152 case 1:
153 *currentProtocol = SCARD_PROTOCOL_T1;
154 break;
155 default:
156 return -3;
157 }
158 }
159
160#ifdef ATR_DEBUG
161 Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
162#endif
163 if (0 == T)
164 {
165 *availableProtocols |= SCARD_PROTOCOL_T0;
166 }
167 else
168 if (1 == T)
169 {
170 *availableProtocols |= SCARD_PROTOCOL_T1;
171 }
172 else
173 if (15 == T)
174 {
175 *availableProtocols |= SCARD_PROTOCOL_T15;
176 }
177 else
178 {
179 /*
180 * Do nothing for now since other protocols are not
181 * supported at this time
182 */
183 }
184 }
185 else
186 Y1i = 0;
187
188 /* test presence of TA2 */
189 if ((2 == i) && (TAi >= 0))
190 {
191 T = TAi & 0x0F;
192#ifdef ATR_DEBUG
193 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
194#endif
195 switch (T)
196 {
197 case 0:
198 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T0;
199 break;
200
201 case 1:
202 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T1;
203 break;
204
205 default:
206 return -4;
207 }
208 }
209
210 /* next interface characters index */
211 i++;
212 }
213 while (Y1i != 0);
214
215 /*
216 * If TDx is not set then the current must be T0
217 */
218 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
219 {
220 *currentProtocol = SCARD_PROTOCOL_T0;
221 *availableProtocols |= SCARD_PROTOCOL_T0;
222 }
223
224#ifdef ATR_DEBUG
225 Log3(PCSC_LOG_DEBUG, "CurrentProtocol: T=%d, AvailableProtocols: %d",
226 *currentProtocol - SCARD_PROTOCOL_T0, *availableProtocols);
227#endif
228
229 return 0;
230}
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