pcsc-lite 1.6.4
atrhandler.c
Go to the documentation of this file.
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 }