pcsc-lite 1.6.4
|
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 4616 2009-12-15 13:32:26Z 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(PSMARTCARD_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 /* 00053 * Zero out everything 00054 */ 00055 p = K = TCK = Y1i = T = 0; 00056 00057 #ifdef ATR_DEBUG 00058 if (dwLength > 0) 00059 LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength); 00060 #endif 00061 00062 if (dwLength < 2) 00063 return 0; 00065 /* 00066 * Zero out the bitmasks 00067 */ 00068 psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNDEFINED; 00069 psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNDEFINED; 00070 00071 /* 00072 * Decode the TS byte 00073 */ 00074 if (pucAtr[0] == 0x3F) 00075 { /* Inverse convention used */ 00076 psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE; 00077 } 00078 else 00079 if (pucAtr[0] == 0x3B) 00080 { /* Direct convention used */ 00081 psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT; 00082 } 00083 else 00084 { 00085 memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); 00086 return 0; 00087 } 00088 00089 /* 00090 * Here comes the platform dependant stuff 00091 */ 00092 00093 /* 00094 * Decode the T0 byte 00095 */ 00096 Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */ 00097 K = pucAtr[1] & 0x0F; /* Get the LSN in K */ 00098 00099 p = 2; 00100 00101 #ifdef ATR_DEBUG 00102 Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X", 00103 psExtension->CardCapabilities.Convention, Y1i, K); 00104 #endif 00105 00106 /* 00107 * Examine Y1 00108 */ 00109 do 00110 { 00111 short TAi, TBi, TCi, TDi; /* Interface characters */ 00112 00113 TAi = (Y1i & 0x01) ? pucAtr[p++] : -1; 00114 TBi = (Y1i & 0x02) ? pucAtr[p++] : -1; 00115 TCi = (Y1i & 0x04) ? pucAtr[p++] : -1; 00116 TDi = (Y1i & 0x08) ? pucAtr[p++] : -1; 00117 00118 #ifdef ATR_DEBUG 00119 Log9(PCSC_LOG_DEBUG, 00120 "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X", 00121 i, TAi, i, TBi, i, TCi, i, TDi); 00122 #endif 00123 00124 /* 00125 * Examine TDi to determine protocol and more 00126 */ 00127 if (TDi >= 0) 00128 { 00129 Y1i = TDi >> 4; /* Get the MSN in Y1 */ 00130 T = TDi & 0x0F; /* Get the LSN in K */ 00131 00132 /* 00133 * Set the current protocol TD1 (first TD only) 00134 */ 00135 if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED) 00136 { 00137 switch (T) 00138 { 00139 case 0: 00140 psExtension->CardCapabilities.CurrentProtocol = 00141 SCARD_PROTOCOL_T0; 00142 break; 00143 case 1: 00144 psExtension->CardCapabilities.CurrentProtocol = 00145 SCARD_PROTOCOL_T1; 00146 break; 00147 default: 00148 return 0; 00149 } 00150 } 00151 00152 #ifdef ATR_DEBUG 00153 Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T); 00154 #endif 00155 if (0 == T) 00156 { 00157 psExtension->CardCapabilities.AvailableProtocols |= 00158 SCARD_PROTOCOL_T0; 00159 } 00160 else 00161 if (1 == T) 00162 { 00163 psExtension->CardCapabilities.AvailableProtocols |= 00164 SCARD_PROTOCOL_T1; 00165 } 00166 else 00167 if (15 == T) 00168 { 00169 psExtension->CardCapabilities.AvailableProtocols |= 00170 SCARD_PROTOCOL_T15; 00171 } 00172 else 00173 { 00174 /* 00175 * Do nothing for now since other protocols are not 00176 * supported at this time 00177 */ 00178 } 00179 } 00180 else 00181 Y1i = 0; 00182 00183 /* test presence of TA2 */ 00184 if ((2 == i) && (TAi >= 0)) 00185 { 00186 T = TAi & 0x0F; 00187 #ifdef ATR_DEBUG 00188 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T); 00189 #endif 00190 switch (T) 00191 { 00192 case 0: 00193 psExtension->CardCapabilities.CurrentProtocol = 00194 psExtension->CardCapabilities.AvailableProtocols = 00195 SCARD_PROTOCOL_T0; 00196 break; 00197 00198 case 1: 00199 psExtension->CardCapabilities.CurrentProtocol = 00200 psExtension->CardCapabilities.AvailableProtocols = 00201 SCARD_PROTOCOL_T1; 00202 break; 00203 00204 default: 00205 return 0; 00206 } 00207 } 00208 00209 if (p > MAX_ATR_SIZE) 00210 { 00211 memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); 00212 return 0; 00213 } 00214 00215 /* next interface characters index */ 00216 i++; 00217 } 00218 while (Y1i != 0); 00219 00220 /* 00221 * If TDx is not set then the current must be T0 00222 */ 00223 if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED) 00224 { 00225 psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0; 00226 psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0; 00227 } 00228 00229 /* 00230 * Take care of the historical characters 00231 */ 00232 psExtension->ATR.HistoryLength = K; 00233 memcpy(psExtension->ATR.HistoryValue, &pucAtr[p], K); 00234 00235 p += K; 00236 00237 /* 00238 * Check to see if TCK character is included It will be included if 00239 * more than T=0 is supported 00240 */ 00241 if (psExtension->CardCapabilities.AvailableProtocols & SCARD_PROTOCOL_T1) 00242 TCK = pucAtr[p++]; 00243 00244 if (p > MAX_ATR_SIZE) 00245 return 0; 00247 memcpy(psExtension->ATR.Value, pucAtr, p); 00248 psExtension->ATR.Length = p; /* modified from p-1 */ 00249 00250 #ifdef ATR_DEBUG 00251 Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d", 00252 psExtension->CardCapabilities.CurrentProtocol, 00253 psExtension->CardCapabilities.AvailableProtocols); 00254 #endif 00255 00256 return 1; 00257 }