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