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