pcsc-lite 1.7.2

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 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 }