pcsc-lite 1.5.5
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 1999-2004 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00007 * 00008 * $Id: atrhandler.c 4344 2009-07-28 10:54:50Z rousseau $ 00009 */ 00010 00021 #include "config.h" 00022 #include <string.h> 00023 00024 #include "misc.h" 00025 #include "pcsclite.h" 00026 #include "debuglog.h" 00027 #include "atrhandler.h" 00028 00033 /* #define ATR_DEBUG */ 00034 00043 short ATRDecodeAtr(PSMARTCARD_EXTENSION psExtension, 00044 PUCHAR pucAtr, DWORD dwLength) 00045 { 00046 USHORT p; 00047 UCHAR K, TCK; /* MSN of T0/Check Sum */ 00048 UCHAR Y1i, T; /* MSN/LSN of TDi */ 00049 int i = 1; /* value of the index in TAi, TBi, etc. */ 00050 00051 /* 00052 * Zero out everything 00053 */ 00054 p = K = TCK = Y1i = T = 0; 00055 00056 #ifdef ATR_DEBUG 00057 if (dwLength > 0) 00058 LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength); 00059 #endif 00060 00061 if (dwLength < 2) 00062 return 0; 00064 /* 00065 * Zero out the bitmasks 00066 */ 00067 psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNDEFINED; 00068 psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNDEFINED; 00069 00070 /* 00071 * Decode the TS byte 00072 */ 00073 if (pucAtr[0] == 0x3F) 00074 { /* Inverse convention used */ 00075 psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE; 00076 } 00077 else 00078 if (pucAtr[0] == 0x3B) 00079 { /* Direct convention used */ 00080 psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT; 00081 } 00082 else 00083 { 00084 memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); 00085 return 0; 00086 } 00087 00088 /* 00089 * Here comes the platform dependant stuff 00090 */ 00091 00092 /* 00093 * Decode the T0 byte 00094 */ 00095 Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */ 00096 K = pucAtr[1] & 0x0F; /* Get the LSN in K */ 00097 00098 p = 2; 00099 00100 #ifdef ATR_DEBUG 00101 Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X", 00102 psExtension->CardCapabilities.Convention, Y1i, K); 00103 #endif 00104 00105 /* 00106 * Examine Y1 00107 */ 00108 do 00109 { 00110 short TAi, TBi, TCi, TDi; /* Interface characters */ 00111 00112 TAi = (Y1i & 0x01) ? pucAtr[p++] : -1; 00113 TBi = (Y1i & 0x02) ? pucAtr[p++] : -1; 00114 TCi = (Y1i & 0x04) ? pucAtr[p++] : -1; 00115 TDi = (Y1i & 0x08) ? pucAtr[p++] : -1; 00116 00117 #ifdef ATR_DEBUG 00118 Log9(PCSC_LOG_DEBUG, 00119 "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X", 00120 i, TAi, i, TBi, i, TCi, i, TDi); 00121 #endif 00122 00123 /* 00124 * Examine TDi to determine protocol and more 00125 */ 00126 if (TDi >= 0) 00127 { 00128 Y1i = TDi >> 4; /* Get the MSN in Y1 */ 00129 T = TDi & 0x0F; /* Get the LSN in K */ 00130 00131 /* 00132 * Set the current protocol TD1 (first TD only) 00133 */ 00134 if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED) 00135 { 00136 switch (T) 00137 { 00138 case 0: 00139 psExtension->CardCapabilities.CurrentProtocol = 00140 SCARD_PROTOCOL_T0; 00141 break; 00142 case 1: 00143 psExtension->CardCapabilities.CurrentProtocol = 00144 SCARD_PROTOCOL_T1; 00145 break; 00146 default: 00147 return 0; 00148 } 00149 } 00150 00151 #ifdef ATR_DEBUG 00152 Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T); 00153 #endif 00154 if (0 == T) 00155 { 00156 psExtension->CardCapabilities.AvailableProtocols |= 00157 SCARD_PROTOCOL_T0; 00158 } 00159 else 00160 if (1 == T) 00161 { 00162 psExtension->CardCapabilities.AvailableProtocols |= 00163 SCARD_PROTOCOL_T1; 00164 } 00165 else 00166 if (15 == T) 00167 { 00168 psExtension->CardCapabilities.AvailableProtocols |= 00169 SCARD_PROTOCOL_T15; 00170 } 00171 else 00172 { 00173 /* 00174 * Do nothing for now since other protocols are not 00175 * supported at this time 00176 */ 00177 } 00178 00179 /* test presence of TA2 */ 00180 if ((2 == i) && (TAi >= 0)) 00181 { 00182 T = TAi & 0x0F; 00183 #ifdef ATR_DEBUG 00184 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T); 00185 #endif 00186 switch (T) 00187 { 00188 case 0: 00189 psExtension->CardCapabilities.CurrentProtocol = 00190 psExtension->CardCapabilities.AvailableProtocols = 00191 SCARD_PROTOCOL_T0; 00192 break; 00193 00194 case 1: 00195 psExtension->CardCapabilities.CurrentProtocol = 00196 psExtension->CardCapabilities.AvailableProtocols = 00197 SCARD_PROTOCOL_T1; 00198 break; 00199 00200 default: 00201 return 0; 00202 } 00203 } 00204 } else 00205 Y1i = 0; 00206 00207 if (p > MAX_ATR_SIZE) 00208 { 00209 memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); 00210 return 0; 00211 } 00212 00213 /* next interface characters index */ 00214 i++; 00215 } 00216 while (Y1i != 0); 00217 00218 /* 00219 * If TDx is not set then the current must be T0 00220 */ 00221 if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED) 00222 { 00223 psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0; 00224 psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0; 00225 } 00226 00227 /* 00228 * Take care of the historical characters 00229 */ 00230 psExtension->ATR.HistoryLength = K; 00231 memcpy(psExtension->ATR.HistoryValue, &pucAtr[p], K); 00232 00233 p += K; 00234 00235 /* 00236 * Check to see if TCK character is included It will be included if 00237 * more than T=0 is supported 00238 */ 00239 if (psExtension->CardCapabilities.AvailableProtocols & SCARD_PROTOCOL_T1) 00240 TCK = pucAtr[p++]; 00241 00242 if (p > MAX_ATR_SIZE) 00243 return 0; 00245 memcpy(psExtension->ATR.Value, pucAtr, p); 00246 psExtension->ATR.Length = p; /* modified from p-1 */ 00247 00248 #ifdef ATR_DEBUG 00249 Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d", 00250 psExtension->CardCapabilities.CurrentProtocol, 00251 psExtension->CardCapabilities.AvailableProtocols); 00252 #endif 00253 00254 return 1; 00255 }